2014-09-11 60 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.