2011-07-26 1 views
1

可能性の重複:私は明らかにここで何かが欠けてい
“Least Astonishment” in Python: The Mutable Default Argumentパイソン - 予期しない動作空のリストのデフォルト値を持つという名前のコンストラクタ引数を使用して

:誰もが「なぜt1を説明することができます奇妙なことに、は、self.thelistの値をt2に取得しますか?私は間違って何をしていますか?

>>> class ThingyWithAList(object): 
...  def __init__(self, alist=[]): 
...   super(ThingyWithAList, self).__init__() 
...   self.thelist = alist 
... 
>>> t1 = ThingyWithAList() 
>>> t1.thelist.append('foo') 
>>> t1.thelist.append('bar') 
>>> print t1, t1.thelist 
<__main__.ThingyWithAList object at 0x1004a8350> ['foo', 'bar'] 
>>> 
>>> t2 = ThingyWithAList() 
>>> print t2, t2.thelist 
<__main__.ThingyWithAList object at 0x1004a8210> ['foo', 'bar'] 
+4

これをチェックしてください:http://stackoverflow.com/questions/1132941/least-astonishment-in-python-the-mutable-default-argument – mouad

+0

@mouad - 素晴らしい、ありがとう!私はこの質問を掲示する前にそれほど注目していませんでしたが、これを見つけられませんでした。 –

答えて

3

デフォルトの引数 'alist = []'は、モジュールを読み込んだときに1回だけリストを作成するため、1回だけリストを作成します。もしこの単一のリストその__init__のデフォルト引数になり」、およびすべてのあなたのThingysによって共有されている。

意味ダミーシンボルとしてNoneを使用していない試してみてください 『』ここに新しい空のリストを作成します。例:

def __init__(self, alist=None): 
    super(ThingyWithAList, self).__init__() 
    self.thelist = [] if alist is None else alist 
+0

ありがとうアドリアン;すばらしい、簡潔な答え。 :) –

2

私はそれが正しい、コンストラクタで[]で作成したオブジェクト参照が同じでもらう代わりにこれを試してみてください:。

>>> class ThingyWithAList(object): 
...  def __init__(self, alist=None): 
...   super(ThingyWithAList, self).__init__() 
...   self.thelist = alist or [] 
... 
>>> t1 = ThingyWithAList() 
>>> t1.thelist.append('foo') 
>>> t1.thelist.append('bar') 
>>> print t1, t1.thelist 
<__main__.ThingyWithAList object at 0xb75099ac> ['foo', 'bar'] 
>>> 
>>> t2 = ThingyWithAList() 
>>> print t2, t2.thelist 
<__main__.ThingyWithAList object at 0xb7509a6c> [] 
+0

あなたの "alistまたは[]"私の[[]よりも良い場合alistはありませんelse alist "。 Perlでは、私はこの種の構文を自動的に考える。PythonではPerlismのように思える。 –

+0

私は他の方法でそれをやるためにPerlには長すぎると思います。 ;-) – igor

+0

優秀、ありがとう! (それはOKですが、私はまだPerlでは時折思っています:-)) –

2

「特殊なケースは十分に特別ではありません」ので、私は間違った方法をこすり条件付きなしのためのチェック。重要なのは.thelistは本当にリストですが、クラスはそれ自体を強制すべきです。

def __init__(self, alist=()): 
    super(ThingyWithAList, self).__init__() 
    self.thelist = list(alist) 

タプルは不変なのでデフォルトのarg nowを変更する危険はないことに注意してください。

関連する問題