2014-09-11 3 views
0

У меня вопрос о наследовании в Python 2.7.Странное поведение наследования классов в Python 2.7

У меня есть два простых классов

class A(): 

    l = [] 

    def f(self): 

     del self.l[:] 

     if self.a == 'a': 
      self.l.append('1') 
     if self.a == 'b': 
      self.l.append('2') 


class B(A): 

    def __init__(self, a): 
     self.a = a 

создать два экземпляра B в цикле и вызвать f() для списка множества «л»

foo = ['a','b'] 
l = [] 

for x in foo: 
    z = B(x) 
    z.f() 
    # normal result 
    print z.l 
    l.append(z) 
print '-----' 

for x in l: 
    # strange result 
    print x.l   

В результате я получаю странный вывод:

Output: 
['1'] 
['2'] 
----- 
['2'] 
['2'] 
[Finished in 0.0s] 

Вместо 1,2; 1,2

Почему это происходит?

я могу это исправить путем определения списка «л» в четкости F (само)

class A(): 

    def f(self): 

     l = [] 

     if self.a == 'a': 
      self.l.append('1') 
     if self.a == 'b': 
      self.l.append('2') 

В этом случае я получаю нормальный выход, но до сих пор не понимаю, почему это происходит.

Благодаря

+0

В качестве примечания стороны: Не используйте 'class A():'. Если это Python 2.x, всегда всегда используйте 'class A (object):', поэтому вы получаете классы нового стиля, особенно когда вы имеете дело с наследованием. Если это Python 3, это менее серьезно, потому что 'class A:', 'class A():' и 'class A (object):' все означают одно и то же, но третье - наиболее явное, первое является самым компактным и простым, а один в середине не имеет преимущества. – abarnert

+0

Также: определение класса 'A', для которого требуется член' self.a', который может быть установлен только подклассом, является немного странным. Есть некоторые случаи, когда это имеет смысл, но почти во всех этих случаях «A» на самом деле является либо mixin, либо [абстрактным базовым классом] (https://docs.python.org/2/library/abc. html), и если это последний, то он более ясен (и полезен для отладки), чтобы определить его таким образом. – abarnert

+0

Спасибо, я понял. – Egregors

ответ

0

Проблема заключается в том, что l не является переменной экземпляра, с каждым A (или B) экземпляр, имеющий свою собственную копию, это переменная типа , разделяемая всеми копиями.

Если вы не хотите переменную класса, просто не определяйте ее. Точно так же вы создаете self.a в B.__init__, создаете self.l в A.__init__.

0

В первом случае l переменная класса и эта переменная разделяется экземплярами класса.

Во втором случае l является переменной экземпляра, поэтому каждый объект имеет свою собственную переменную.

Обратите внимание, что это не имеет ничего общего с наследованием - вы увидите такое же поведение, если инстанцировании либо класс A или B.

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