2017-08-04 22 views
3

私はこれを行うことができます:派生クラスの基本クラスの属性を参照する方法は?

class Blah1: 
    atttr = 5 


class Blah2(Blah1): 
    aa = atttr 


ob = Blah2 
print(ob.aa) 

いや、私はできません:http://ideone.com/6HS1MO

を出してくれるので、私は私もこれを行うことが想定さ

class Blah2: 
    atttr = 5 
    aa = atttr 


ob = Blah2 
print(ob.aa) 

http://ideone.com/pKxMc2

を次のエラー:

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 

EDIT:WIMの答えで述べたように、これの原因はスコープがクラス定義の内部でどのように動作するかである今、あなたはこれを持っています。あなたがこれを行うときは:あなたが見ることができるようにそのaどこでもクラス定義本体の外に、あなたが参照する必要にアクセスするためには、

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

class C(): 
    a = 1 

をそれはこれにほとんど同じですクラス(またはクラスのインスタンス)を使用して:C.aまたはc().a。しかし、注意して、この「落とし穴」:

class C(): 
    a = 1 

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

上記二行目の後に、今c属性aC属性aの両方があるのでそれは1を出力し、そして、彼らは2つの異なるオブジェクトです:

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

c.aC.aを上書きしないようにするには、プロパティとディスクリプタについて学習する必要があります。たぶんhereを開始します。