2014-09-11 56 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的两个实例,并呼吁集列表“L”

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   

在结果f()我得到了奇怪的输出:

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

改为1,2; 1,2

这是怎么发生的?

我可以安排在DEF F(个体经营)

class A(): 

    def f(self): 

     l = [] 

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

在这种情况下,我得到正常的输出定义列表“L”,但还是不明白为什么会这样。

由于

+0

附注:不要使用'class A():'。如果这是Python 2.x,那么总是总是使用'class A(object):',这样就可以获得新风格的类,特别是在处理继承时。如果这是Python 3,那就不那么严重了,因为'A类:','类A():'和类A(对象):'都表示同样的东西 - 但是第三个是最明确的,第一个是最紧凑和最简单的,而中间的一个没有优势。 – abarnert 2014-09-11 04:32:09

+0

另外:定义一个类'A'需要一个只能由子类设置的成员'self.a',这有点奇怪。在某些情况下,这是有道理的,但在几乎所有这些情况下,'A'实际上是一个mixin或一个[抽象基类](https://docs.python.org/2/library/abc。 html),如果它是后者,则更清晰(并且对于调试非常有用)以这种方式进行定义。 – abarnert 2014-09-11 04:35:02

+0

谢谢,我明白了。 – Egregors 2014-09-11 12:40:41

回答

0

的问题是,l不是一个实例变量,每个A(或B )实例拥有自己的副本,它是一个变量,由所有副本共享。

如果你不想要一个类的变量,只是不要定义一个。您在B.__init__中创建self.a的相同方式,在A.__init__中创建self.l

0

在第一种情况,l是一个类变量和该变量是由类的实例共享。

在第二种情况下,l是一个实例变量,因此每个对象都有自己的变量。

注意,这已经无关,与遗传 - 你会看到同样的行为,如果实例类A或B.