Pythonの中のいくつかの属性の訪問の違いと使い方の詳細


スタートをきる
Pythonでは、オブジェクトの属性に対するアクセスは、点(.)属性演算子を用いて行います。例えば、あるクラスのインスタンスオブジェクトfooがあり、それはname属性を持っています。foo.nameを使用してこの属性にアクセスすることができます。一般的には、ポイント(.)属性演算子は直感的で、私たちがよく出会う属性のアクセス方法です。
pythonの提供に関する一連の特殊方法と属性のアクセスget_,_getattr_,_getattribute_,_getitem_u。本文はそれらの違いと使い方を述べます。
属性のアクセス機構
一般に、属性アクセスのデフォルトの挙動は、対象の辞書から取得され、取得できない場合は、一定のルックアップチェーンに沿って検索される。例えばa.xのルックアップチェーンは、a.u_udict_[]x',次はtype(a)._u udict_[]x']は、type(a)の基質から検索を開始します。
検索チェーンが属性を取得できない場合は、アトリエ異常をスローします。
同前getattr方法
同前getattr関数の役割:属性検索(atribute lookup)がインスタンスおよび対応するクラスにある場合(__u u uを介して)dict失敗したら、クラスの_u u uを呼び出します。getattr関数は、この関数を定義していないと、アトリエ異常をスローします。このことから分かるようにgetattr属性検索の最後のステップになります。
この方法は、オブジェクトの属性が存在しない場合は呼び出しです。正常な仕組みでオブジェクトの属性が見つけられたら、__u u_uを呼び出しません。getattr方法。

class A:
 a = 1
 def __getattr__(self, item):
 print('__getattr__ call')
 return item

t = A()
print(t.a)
print(t.b)
# output
1
__getattr__ call
b
同前getattribute_u u方法
この方法は無条件に呼び出される。属性の有無を問わず。クラスの中で定義されている場合は、__u ugetattr_u,はコールできませんgetattr_()方法としては、__u唵にない限りgetattribute_u uメソッドに呼び出しを表示します。getattr_()あるいはアトリエを投げ出しました。

class A:
 a = 1
 def __getattribute__(self, item):
 print('__getattribute__ call')
 raise AttributeError

 def __getattr__(self, item):
 print('__getattr__ call')
 return item

t = A()
print(t.a)
print(t.b)
ですから、一般的には、_u u_を残すためにgetattrの役割を果たすgetattribute()方法では、一般的に親の名前を返します。

def __getattribute__(self, item):
 return object.__getattribute__(self, item)
基本クラスの方法を用いて,属性を取得することは,方法に無限再帰が生じることを避けることができる。
同前ゲットする方法
この方法は比較的簡単に説明されていますが、前のものとはあまり関係がありません。
一つのクラスの中で定義したら__u u uget_,_set_()または_delete_()のいずれかの方法があります。このクラスのオブジェクトを記述子と呼びます。

class Descri(object):
 def __get__(self, obj, type=None):
 print("call get")

 def __set__(self, obj, value):
 print("call set")

class A(object):
 x = Descri()

a = A()
a.__dict__['x'] = 1 #      __get__
a.x  #    __get__
検索の属性が記述子オブジェクトである場合、この記述子は上記で述べた属性アクセス機構をカバーし、ルックアップチェーンの違いによって表されるが、この行も呼び出しの違いによって少し違ってくる。
  • コールがオブジェクトインスタンス(タイトル中のコール方式)である場合、a.xは呼び出しに変換される。type(a)._udict_[]x._u.get_.a、type(a)
  • 呼び出しがクラス属性である場合、A.xはA._u udict_[]x._u.get_.ノン、A)
  • その他の場合は、文末参照資料のドキュメント
  • を参照してください。
    同前getitem_u u方法
    この呼び出しは無条件呼出にもなります。getattribute_u u一致します。違いは__uにありますgetitem_u uクラスのインスタンスに[]演算を許可させることは、このように理解される。
  • _u u_getattribute_u uすべてに適用します。演算子;
  • _u u_getitem_u uすべての[]演算子に適用されます。
  • 
    class A(object):
     a = 1
    
     def __getitem__(self, item):
     print('__getitem__ call')
     return item
    
    t = A()
    print(t['a'])
    print(t['b'])
    オブジェクトのみが欲しい場合は、[]でオブジェクト属性を取得することができます。
    
    def __getitem(self, item):
     return object.__getattribute__(self, item)
    締め括りをつける
    これらの方法が同時に現れるとあなたを邪魔するかもしれません。ネットで一つの例を見たらいいです。ちょっと変えました。
    
    class C(object):
     a = 'abc'
    
     def __getattribute__(self, *args, **kwargs):
     print("__getattribute__() is called")
     return object.__getattribute__(self, *args, **kwargs)
    
     # return "haha"
     def __getattr__(self, name):
     print("__getattr__() is called ")
     return name + " from getattr"
    
     def __get__(self, instance, owner):
     print("__get__() is called", instance, owner)
     return self
    
     def __getitem__(self, item):
     print('__getitem__ call')
     return object.__getattribute__(self, item)
    
     def foo(self, x):
     print(x)
    
    class C2(object):
     d = C()
    
    if __name__ == '__main__':
     c = C()
     c2 = C2()
     print(c.a)
     print(c.zzzzzzzz)
     c2.d
     print(c2.d.a)
     print(c['a'])
    アウトプットを結合してゆっくりと理解できますが、ここではまだ相続関係には触れていません。とにかく、一つ一つをグウでgetはプレフィクスの方法で、対象内部データを取得するフックです。名前が違っています。用途にも大きな違いがあります。実際に理解してこそ、それらの使い方を本当に身につけることができます。
    はい、以上はこの文章の全部の内容です。本文の内容は皆さんの学習や仕事に対して一定の参考学習価値を持っています。質問があれば、メッセージを残して交流してください。ありがとうございます。