2011-01-30 3 views
73

Как-то в классе Node ниже переменная wordList и adjacencyList разделяется между всеми экземплярами узла.Конструктор 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 и переменный список смежных вершин?

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

+1

возможно дубликат [Как я должен объявить значения по умолчанию для переменных экземпляра в Python?] (Http://stackoverflow.com/questions/2681243/how-should-i-declare-default-values-for- instance-variables-in-python) –

+0

Возможный дубликат [«Наименьшее удивление» в Python: какая область действия является аргументом Mutable Default Argument в?] (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

Это также могут быть однострочные: 'self.wordList = wordList, если wordList не является None else []', или , немного менее безопасным, 'self.wordList = wordList или []'. –

+1

Это считается путинским способом, но я предпочитаю путь круси, потому что «особые случаи не достаточно специальные». –

+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.

Как указывали другие плакаты, вы, вероятно, захотите использовать None в качестве значения дозорного и предоставить каждому экземпляру собственный список.

11
class Node: 
    def __init__(self, wordList=None adjacencyList=None): 
     self.wordList = wordList or [] 
     self.adjacencyList = adjacencyList or [] 
Смежные вопросы