2017-08-04 123 views
3

我可以這樣做:如何在派生類中引用基類的屬性?

class Blah2: 
    atttr = 5 
    aa = atttr 


ob = Blah2 
print(ob.aa) 

http://ideone.com/pKxMc2

所以,我認爲我可以,以及這樣做:

class Blah1: 
    atttr = 5 


class Blah2(Blah1): 
    aa = atttr 


ob = Blah2 
print(ob.aa) 

都能跟得上我不能:http://ideone.com/6HS1MO

吐出來以下錯誤:

Traceback (most recent call last): 
    File "./prog.py", line 5, in <module> 
    File "./prog.py", line 6, in Blah2 
NameError: name 'atttr' is not defined 

爲什麼不工作,以及如何使它工作?

+0

您應該首先創建這些類的實例,而不是訪問類本身的屬性。 –

+0

爲什麼你需要這樣做?你知道'Blah2'和'Blah1'是*類*,而不是*實例*,是的?實例繼承父類的字段,而不是類 –

回答

2

類定義中的類塊範圍僅臨時存在。在定義類之後,您必須通過類對象訪問該屬性,即Blah1.atttr

這記錄在execution model部分。

Class definition blocks and arguments to exec() and eval() are special in the context of name resolution. A class definition is an executable statement that may use and define names. These references follow the normal rules for name resolution with an exception that unbound local variables are looked up in the global namespace. The namespace of the class definition becomes the attribute dictionary of the class. The scope of names defined in a class block is limited to the class block; it does not extend to the code blocks of methods – this includes comprehensions and generator expressions since they are implemented using a function scope.

1

問題得到解決這樣的:

class Blah1: 
    atttr = 5 


class Blah2(Blah1): 
    aa = BLah1.atttr 

然而,在評論中指出,這是做一個奇怪的事情。現在你有這個:

>>> ob = Blah2() 
>>> assert ob.aa == ob.atttr 
True 

編輯:正如wim的答案中所述,原因是如何範圍內工作的類定義。當你這樣做:

class C(): 
    a = 1 

這是非常相同的:

C = type('C',(), {}) # <--- dynamic class creation function 
C.a = 1 

正如你所看到的,爲了訪問a類定義體以外的任何地方,你必須參考使用類(或類的一個實例):C.ac().a。但要注意這種「疑難雜症」:

class C(): 
    a = 1 

c = C() 
c.a = 2 
print(C.a) # prints 1!!! 

它打印1,因爲上面的第二個行之後,現在有兩個一個c屬性aC屬性a,他們是兩個不同的對象:

>>> vars(c) 
{'a': 2} 
>>> vars(C) 
{'a': 1} 

如果你想c.a不覆蓋C.a,你需要了解屬性和描述符。也許開始here