2016-07-07 8 views
4

は、次のことを考えてみましょう:__getattribute__はいつ属性検索に関与しませんか?

class A(object): 
    def __init__(self): 
     print 'Hello!' 

    def foo(self): 
     print 'Foo!' 

    def __getattribute__(self, att): 
     raise AttributeError() 

a = A() # Works, prints "Hello!" 
a.foo() # throws AttributeError as expected 

__getattribute__の実装は、明らかに、すべてのルックアップに失敗しました。私の質問:

  • なぜオブジェクトをインスタンス化できますか?私は__init__メソッド自体のルックアップも失敗すると予想していました。
  • __getattribute__の対象外の属性の一覧は何ですか?

答えて

2

__getattribute__の実装では、明らかに、すべての検索

だが、それはすべてのバニラの検索に失敗したとしましょう失敗します。

__getattribute__は、クラスの属性でもあるので、最初はどのように呼び出されましたか?


属性は、ドットに続く任意の名前を参照します。だからクラスインスタンスのを取得するには、その属性に(ドット参照で)アクセスしようとすると無条件に__getattribute__が呼び出されます。

魔法のようなもの__init__は、言語構成の一部であり、言語の一部として実装されているため直接(ドット参照で)呼び出されません。

なぜオブジェクトをインスタンス化できますか?

あなたは:

a = A() 

__init__方法がなく、バニラ検索を経由して、舞台裏で呼び出されます。言語がこれを処理します。 __setattr__,__delattr__,__getattribute__などの他のメソッドにも同じです。

しかし、あなたが直接__init__呼び出された場合:

a.__init__() 

それはエラーが発生します。クラスが既に初期化されているので、これは意味をなさない。もっと微妙

、あなたがドット参照を経由して、あなたのクラスのインスタンスから__getattribute__にアクセスしようとした場合:

a.__getattribute__ 

を、それはまたAttributeErrorを引き上げます。同じメソッドの言語呼び出しが属性__getattribute__をルックアップしようとしましたが、エラーで失敗しました。


__getattribute__の対象ではありません属性のリストは何ですか?

__getattribute__は、ドット参照で任意の属性にアクセスしようとすると表示されます。あなたが明示的にという魔方法を呼び出そうとしない限り、__getattribute__は呼び出されません。

+0

'.__ dict__'にアクセスすると' __getattribute __() 'は呼び出されません。 – zondo

+0

ああ、私は今の違いを参照してください。私は授業の外でもそれが真実だと思った。私はちょうどいくつかのテストを行いました。クラス本体の外で '.__ dict__'にアクセスすると' __getattribute__'が呼び出されますが、 '__getattr__'は呼び出されません。私はなぜ彼らが区別を作ったのだろうか。 – zondo

+1

@zondo 'self .__ dict__'にアクセスするには' __getattribute__'も必要です。 '__getattr__'は、属性が' __getattribute__'によって見つからないときに最後の手段として呼び出されます。 –

関連する問題