2013-10-06 67 views
2

我試圖用調用另一個方法的方法實現一個類,該對象是最低方法變異對象的一部分。我的實現是一個有點複雜,所以我會後只是一些假的代碼,所以你可以看到我在談論:Python:將可變(?)對象傳遞給方法

class test: 
    def __init__(self,list): 
     self.obj = list 
    def mult(self, x, n): 
     x = x*n 
    def numtimes(self, n): 
     self.mult(self.obj, n) 

現在,如果我創建這個類型的對象並運行numtimes方法,它不會更新self.obj:

m = test([1,2,3,4]) 
m.numtimes(3) 
m.obj #returns [1,2,3,4] 

雖然我希望它給我[1,2,3,4,1,2,3,4,1,2,3,4 ]

基本上,我需要通過self.obj到MULT方法,並將它發生變異self.obj這樣,當我打電話m.obj,我會得到[1,2,3,4,1,2 ,3,4,1,2,3,4]而不是[1,2,3,4]。我覺得這只是一個理解python如何將對象作爲參數傳遞給方法的問題(比如它創建了對象的副本,而不是我需要使用指針),但也許不是。我是python的新手,真的可以在這裏使用一些幫助。

在此先感謝!

+0

Python沒有指針;當你將一個變量傳遞給一個函數時,你只是將函數參數綁定到變量綁定的相同值。如果這是一個可變的值,你可以改變它。你的問題是'x = whatever'只是重新綁定局部變量'x',它不會改變任何東西。 – abarnert

+0

同時,你是否真的需要在原地進行'self.obj'的變異?如果'mult'只是'返回x * n',並且'numtimes'確實'self.obj = self.mult(self.obj,n)',那會起作用嗎?這不適用於每個用例(例如,如果'self.obj'是一個10000x10000矩陣,您可能不想創建額外的副本;如果其他代碼具有對'self.obj'的引用並需要查看改變,製作副本不會有幫助)......但是當它發生時,它通常更簡單。 – abarnert

+0

感謝您解決這個問題。回想起來,我認爲我應該在'mult'中包含一個數組元素賦值,因爲這真的是我想要做的最重要的操作。我只是爲了簡單而使用'x = x * n',但是我意識到它會讓事情變得混亂。我真的需要根據'mult'方法中的某些邏輯來改變'self.obj'的元素。 – nViz

回答

2

請允許我利用上的可變性更大的問題。

列表是可變對象,並支持可變操作和不可變操作。這意味着,就地更改列表的操作以及返回新列表的操作。相比之下,元組只有不可變。

所以,乘以一個列表,你可以選擇兩種方法:

  1. 一個* = B

這是一個可變操作,將在 'A' 改變-地點。

  1. A = A * B

這是一個不可變操作。它將評估'a * b',使用正確的值創建一個新列表,並將'a'分配給該新列表。

這裏,已經解決了您的問題。但是,我建議你稍微閱讀一下。當你將列表(和其他對象)作爲參數傳遞時,你只傳遞一個新的引用或「指針」到同一個列表。因此,在該列表上運行可變操作也會改變您傳遞的操作。結果可能是一個非常微妙的錯誤,當你寫:

>>> my_list = [1,2,3] 
>>> t = test(my_list) 
>>> t.numtimes(2) 
>>> my_list 
[1,2,3,1,2,3] # Not what you intended, probably! 

所以這是我最後的建議。你可以選擇使用可變操作,這很好。但後來從參數創建一個新的副本,因爲這樣的:

def __init__(self,l): 
    self.obj = list(l) 

或使用一成不變的操作,並重新分配給自己:

def mult(self, x, n): 
    self.x = x*n 

或者兩者都做,有一個在爲額外的安全無危害: )

+0

是否有變異數組賦值操作?所以,假設我可以將self.obj作爲參數傳遞給mult,我將其中的一部分複製到一個虛擬列表中,並將一個(排序的)版本重新複製到self.obj,這樣我就可以訪問self.obj的排序版本以後在那個方法之外? – nViz

+0

你在尋找可變的「賦值」列表嗎?因爲這是可能的:my_list [:] = [1,2,3,4] 此外,您可以使用切片來更改列表的一部分,即更改最後三個元素:my_list [-3:] = [1, 2,3] – Erez

3

乘法x * n創建一個新實例,不會更改現有列表。在這裏看到:

a = [1] 
print (id (a)) 
a = a * 2 
print (id (a)) 

這應該工作:

class test: 
    def __init__(self,list): 
     self.obj = list 

    def mult(_, x, n): 
     x *= n 

    def numtimes(self, n): 
     self.mult(self.obj, n) 
+0

很好的答案,但它並不能解釋'x = x * n'和'x * = n'之間的區別。第一個調用'x .__ mult__(n)',它應該是一個非變異函數,並將結果賦給'x',這不會影響其他任何對原始值有參考的人呼叫者)。第二個調用'x .__ imult __(n)',它應該在可能的情況下進行變異,這意味着_does_會影響引用了原始值的其他人。或者,也許只是顯示'a * = 2; print(id(a))'而不是試圖解釋細節。 – abarnert