2012-03-20 46 views
2

可能重複:
「Least Astonishment」 in Python: The Mutable Default Argument蟒蛇:問題類對象的列表:所有項目都是相同的

我試圖創建該類的對象列表「 fooclass「,具有不同的屬性,但總是以包含相同值的列表中的所有元素結束。

這裏是我運行代碼:

#!/usr/bin/env python 

class fooclass(): 
    def __init__(self,vertices = [[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0]]): 
    self.vertices = vertices 

l=[] 
print(l) 
a=fooclass(); a.vertices[0]=[7,9,9]; l.append(a) 
print 'a=', a.vertices 
a=fooclass(); a.vertices[0]=[789,9,9]; l.append(a) 
print 'a=', a.vertices 
print(l[0].vertices) 
print(l[1].vertices) 
print(l) 

l=[] 
print(l) 
a=fooclass(); a.vertices[0]=[7,9,9]; l.append(a) 
print 'a=', a.vertices 
b=fooclass(); b.vertices[0]=[789,9,9]; l.append(b) 
print 'b=', b.vertices 
print(l[0].vertices) 
print(l[1].vertices) 
print(l[0]) 
print(l[1]) 

和輸出我得到:

$ python ./class_test2.py 
[] 
a= [[7, 9, 9], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]] 
a= [[789, 9, 9], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]] 
[[789, 9, 9], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]] 
[[789, 9, 9], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]] 
[<__main__.fooclass instance at 0x7f945eafecf8>, <__main__.fooclass instance at 0x7f945eafed88>] 
[] 
a= [[7, 9, 9], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]] 
b= [[789, 9, 9], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]] 
[[789, 9, 9], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]] 
[[789, 9, 9], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]] 
<__main__.fooclass instance at 0x7f945eafecf8> 
<__main__.fooclass instance at 0x7f945eafed88> 

爲什麼L [0] .vertices和L [1] .vertices完全相同,儘管同輸入不同的值?

系統信息:

Ubuntu 10.04.4 LTS 
$ python --version 
Python 2.6.5 
$ uname -a 
Linux *** 2.6.32-39-generiC#86-Ubuntu SMP Mon Feb 13 21:50:08 UTC 2012 x86_64 GNU/Linux 

注:與Python 3.1.2(只是改變了打印語句),同樣的問題試過。 。:(

+5

嘆了口氣,在[可變默認參數(http://stackoverflow.com/questions/1132941/least-astonishment-in-python-the-mutable-default-argument)再次... – 2012-03-20 17:12:14

+0

此外,繼承類從「對象」出發,或者在需要更高級的功能時受到令人討厭的難以捉摸的行爲的影響。 (不從對象繼承的類是Python 2中的「舊式」類,並且不支持所有可用的功能) – jsbueno 2012-03-20 17:40:03

+0

感謝您的警告。只是爲所有的父類做了這些(因爲它似乎不適用於從父母繼承的子類)。 – KIAaze 2012-03-20 17:56:58

回答

5

verticescan be modified in Python的默認值,可以重寫__init__像這樣避免:

def __init__(self, vertices=None): 
    if vertices is None: 
     vertices = [[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0]] 
    self.vertices = vertices 
+0

謝謝。它使類更長(因爲我有很多默認參數),但至少它可以工作。 – KIAaze 2012-03-20 17:46:41

2

當您設置默認參數vertices = [...],你實際上是實例化一個列表對象使用每一次的說法是不確定這意味着雙方的fooclass實例共享 - 並修改 - 一個列表

相反,它實例__init__方法,如果沒有給出該參數的值。這確保每次運行該方法時都會創建一個新的。

編輯: phihag的答案給出了糾正__init__的很好的示例代碼。