2010-03-08 43 views
5

假設你有這樣的事情:Python實例和屬性:這是一個錯誤還是我完全錯了?

class intlist: 
     def __init__(self,l = []): 
       self.l = l 
     def add(self,a): 
       self.l.append(a) 

def appender(a): 
     obj = intlist() 
     obj.add(a) 
     print obj.l 

if __name__ == "__main__": 
     for i in range(5): 
       appender(i) 

一個函數創建intList中的實例,並在這個新的實例的方法追加在實例屬性升調用。

如何產生該代碼的輸出是:

[0]

[0,1]

[0,1,2]

[0,1,2 ,3]

[0,1,2,3,4]

? 如果切換

obj = intlist() 

obj = intlist(l=[]) 

我得到所需的輸出

[0]

[1]

[2]

[3]

[4]

爲什麼會發生這種情況?

感謝

+0

+1措辭這個這樣的問題,並從一開始就承認錯誤。這就是我們學習的方式! :) – jathanism 2010-03-08 17:01:24

+0

相關:http://stackoverflow.com/questions/1011431/python-things-one-must-avoid – 2010-03-08 17:07:42

+0

謝謝大家,現在我明白了,我必須更多關注我作爲默認值使用的內容。再次感謝:) – 2010-03-09 09:51:35

回答

14

啊,你已經打了常見的Python陷阱之一:默認值計算一次,然後重新使用。所以,每次調用__init__時,都會使用相同的列表。

這是做你想要什麼樣的Python的方式:

def __init__(self, l=None): 
    self.l = [] if l is None else l 

對於位的更多信息,(即標題後特別是約三段)退房the Python docs

編輯:有a much better description in another answer

+4

沒錯。一般來說,你可能不想使用可變類型作爲默認值。 – prestomation 2010-03-08 16:44:31

+0

請注意:在我最初的回答中,我使用了'self.l = l或[]'......在這種情況下,這可能是正確的,但這是一個危險的習慣(例如:my_list = [] ; intlist(my_list); my_list.append(4)'可能不會做你想要的)。 – 2010-03-08 16:51:04

+0

+1:標準問題 - 可變對象作爲默認值。看到所有這些解釋:http://stackoverflow.com/search?q=%5Bpython%5D+mutable+default+values – 2010-03-08 17:06:33

1

行爲的發生是因爲你__init__方法共享所有調用相同的默認列表。

嘗試:

class intlist: 
     def __init__(self, l): 
       self.l = l if (l is not None) else [] 
     def add(self,a): 
       self.l.append(a) 

編輯:使用is not,每SilentGhost

+0

'是'是'None'的慣用測試。 – SilentGhost 2010-03-08 16:44:16

3

的問題是,你說的

def __init__(self,l = []): 

當你告訴Python中使用相同的列表,[],爲構造函數的每次調用。所以每次調用obj = intlist()時都會追加相同的列表。

您應該做的是將l設置爲缺省值None,這是一個標量(因此,如果多次使用,您的代碼將按預期工作)。然後,如果lNone,則將新類成員初始化爲[]。否則,只需將成員變量分配給l即可。

0

請注意列表和字典等類型的默認參數。 intlist的每個實例從默認參數獲取相同的列表對象。

4

當您在__init__中設置默認值l=[]時,您實際上每次都使用相同的列表。相反,你可以嘗試像:

class intlist: 
    def __init__(self, l=None): 
     if l is None: 
      self.l = [] 
     else: 
      self.l = l 
+1

+ 1,'是無'是完全正確的方式來檢查這裏(不是'==沒有'或僅僅根據'l'的真值作爲其他答案的建議!)。 – 2010-03-08 16:44:59

1

obj = intlist()調用你__init__()功能,使用相同的數組類的每一個實例。

obj = intlist(l=[])爲每個實例創建一個新數組。

相關問題