2010-04-19 5 views
4

Посмотрите этот простой пример. Я не совсем понимаю, почему o1 печатает «Hello Alex» дважды. Я думаю, что из-за по умолчанию self.a всегда возвращается в пустой список. Может ли кто-нибудь объяснить мне, что здесь является обоснованием? Огромное спасибо.Простой python oo issue

class A(object): 
     def __init__(self, a=[]): 
      self.a = a 

o = A() 
o.a.append('Hello') 
o.a.append('Alex') 
print ' '.join(o.a) 

# >> prints Hello Alex 

o1 = A() 
o1.a.append('Hello') 
o1.a.append('Alex') 
print ' '.join(o1.a) 

# >> prints Hello Alex Hello Alex 
+1

это даже упоминается в документации: http://docs.python.org/tutorial/controlflow.html#default-argument-values ​​-> «Важное предупреждение» - насколько это очевидно? – hop

+1

не то, что очевидно и вполне противостоят интуитивно понятным. –

ответ

6

аргументы по умолчанию в Python, как:

def blah(a="default value") 

оцениваются раз и повторно использовать в каждом вызове, поэтому, когда вы изменяете изменении глобально. Возможное решение сделать:

def blah(a=None): 
    if a is None 
    a = [] 

Вы можете прочитать больше об этой проблеме на: http://www.ferg.org/projects/python_gotchas.html#contents_item_6

В принципе, никогда не использовать изменяемые объекты, как списки или словари на значение по умолчанию для аргумента.

12

Прочитайте эту Pitfall об изменяемых аргументов функции по умолчанию: http://www.ferg.org/projects/python_gotchas.html

Короче говоря, когда вы определяете

def __init__(self,a=[]) 

В списке ссылается self.a по умолчанию определяется только один раз, время определения, а не время выполнения. Поэтому каждый раз, когда вы вызываете o.a.append или o1.a.append, вы изменяете тот же список.

Типичный способ исправить это, чтобы сказать:

class A(object): 
    def __init__(self, a=None): 
     self.a = [] if a is None else a 

Перемещая self.a=[] в тело функции __init__, новый пустой список создается во время выполнения (каждый раз __init__ называется), а не во время определения.

+0

Исправьте это следующим образом: 'class A (Object): def __init __ (self, a = None): self.a = a, если a не является None else []' – badp

+0

Спасибо, bp, :-) – unutbu

Смежные вопросы