Конструктор Python и значение по умолчанию

Как бы то ни было, в классе Node ниже переменная wordList и adjacencyList разделяется между всеми экземплярами 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']

Можно ли каким-либо образом использовать значение по умолчанию (пустой список в этом случае) для параметров конструктора, но чтобы получить как a, так и b, чтобы иметь свои собственные переменные listList и adjacencyList?

Я использую python 3.1.2.

Ответ 1

Переменные аргументы по умолчанию обычно не делают то, что вы хотите. Вместо этого попробуйте следующее:

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 

Ответ 2

Давайте проиллюстрируем, что происходит здесь:

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 в качестве контрольного значения и предоставить каждому экземпляру собственный список.

Ответ 3

Я бы попробовал:

self.wordList = list(wordList)

чтобы заставить его сделать копию вместо ссылки на один и тот же объект.

Ответ 4

class Node:
    def __init__(self, wordList=None adjacencyList=None):
        self.wordList = wordList or []
        self.adjacencyList = adjacencyList or []