web-dev-qa-db-ja.com

Pythonコンストラクターとデフォルト値

どういうわけか、以下のNodeクラスでは、wordListname__およびadjacencyListname__変数がNodeのすべてのインスタンス間で共有されます。

>>> 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']

コンストラクタパラメータにデフォルト値(この場合は空のリスト)を使用し続ける方法はありますが、aname__とbname__の両方に独自のwordListname__とadjacencyListname__変数を設定するには

python 3.1.2を使用しています。

97
Hery

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

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 
118

ここで何が起こっているかを説明しましょう:

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になります。

他のポスターが指摘しているように、おそらくNoneを番兵値として使用し、各インスタンスに独自のリストを指定する必要があります。

29
aaronasterling
class Node:
    def __init__(self, wordList=None adjacencyList=None):
        self.wordList = wordList or []
        self.adjacencyList = adjacencyList or []
17
Shankar Cabus

私が試してみる:

self.wordList = list(wordList)

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

16
krousey