2011-01-30 18 views
73

どういうわけか、下のNodeクラスでは、wordListとadjacencyList変数がNodeのすべてのインスタンス間で共有されています。Pythonのコンストラクタとデフォルト値

>>> class Node: 
...  def __init__(self, wordList = [], adjacencyList = []): 
...   self.wordList = wordList 
...   self.adjacencyList = adjacencyList 
... 
>>> a = Node() 
>>> b = Node() 
>>> a.wordList.append("hahaha") 
>>> b.wordList 
['hahaha'] 
>>> b.adjacencyList.append("hoho") 
>>> a.adjacencyList 
['hoho'] 

私は、コンストラクタのパラメータのデフォルト値(この場合は空のリスト)を使用し続けることができますが、自分のwordListにし、隣接リストの変数を持つようにAとBの両方を取得する方法はありますか?

私はpython 3.1.2を使用しています。

+1

の可能重複〔どのように私はPythonでインスタンス変数のデフォルト値を宣言する必要がありますか?](http://stackoverflow.com/questions/2681243/how-should-i-declare-default-values-for- –

+0

Pythonの["Least Astonishment"の可能な複製:どのスコープが変更可能なデフォルト引数ですか?](http://stackoverflow.com/questions/1132941/least-astonishment-in-python -which-scope-is-the-mutable-default-argument-in) –

答えて

91

変更可能なデフォルトの引数は、通常、あなたが望むものを実行しません。代わりに、これを試してみてください。

class Node: 
    def __init__(self, wordList=None, adjacencyList=None): 
     if wordList is None: 
      self.wordList = [] 
     else: 
      self.wordList = wordList 
     if adjacencyList is None: 
      self.adjacencyList = [] 
     else: 
      self.adjacencyList = adjacencyList 
+20

これらは1ライナーでもあります: 'wordListがNone else []'でない場合は 'self.wordList = wordList 、少し安全性が低い、 'self.wordList = wordList or []'。 –

+1

これはPythonの方法と見なされますが、「特別なケースは十分ではないので」私はkrouseyの方法を好む。 –

+0

@JoshBleecherSnyder私は指先を置くことができませんでした。 – markdsievers

15

私がしようとするだろう:

self.wordList = list(wordList) 

代わりに、同じオブジェクトを参照のコピーを作成することを強制します。

+1

+1のように簡略化されています:) – Hery

23

だが、ここで何が起こっているのか説明してみましょう:

Python 3.1.2 (r312:79147, Sep 27 2010, 09:45:41) 
[GCC 4.4.3] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> class Foo: 
...  def __init__(self, x=[]): 
...   x.append(1) 
... 
>>> Foo.__init__.__defaults__ 
([],) 
>>> f = Foo() 
>>> Foo.__init__.__defaults__ 
([1],) 
>>> f2 = Foo() 
>>> Foo.__init__.__defaults__ 
([1, 1],) 

あなたはデフォルト引数が問題になっている関数の属性であるタプルに格納されていることがわかります。これは実際に問題のクラスとは無関係で、どんな関数にも向いています。 Python 2では、属性はfunc.func_defaultsになります。

他のポスターが指摘しているように、をセンチネル値として使用し、それぞれのインスタンスに独自のリストを与えることをお勧めします。

11
class Node: 
    def __init__(self, wordList=None adjacencyList=None): 
     self.wordList = wordList or [] 
     self.adjacencyList = adjacencyList or [] 
関連する問題