2016-10-05 10 views
-3

クラスの構築でデータ記述子を使用しているときに、クラスのgetattr関数の異常な動作が発生しました。 RHSはStringのインスタンスを返しながらデータ記述子を持つクラスのgetattrの使用

# this is a data descriptor 
class String(object): 
    def __get__(self, instance, owner): 
     pass 
    def __set__(self, instance, value): 
     pass 

# This defines a class A with 'dot' notation support for attribute 'a' 
class A(object): 
    a = String() 

obj = A() 
assert getattr(A, 'a') is A.__dict__['a'] 
# This raises AssertionError 

LHSは、空の文字列を返します。オブジェクト上のgetattrは、__dict__の中のキーの値を取得することだと思いました。 getattr関数はクラスオブジェクトに対してどのように機能しますか?

+0

「None」ではなく空の文字列を返してもよろしいですか? – Bakuriu

+0

* LHSは空の文字列を返す*確かに?私が試しているように、 'None'を返します。それはどうしていけないのですか?あなたはディスクリプタでそう言います! – glglgl

+1

BTW: 'A.a'は**ではありません**' A .__ dict __ ['a'] 'と同じです。最初のものだけが「属性メカニズム全体」をトリガします。 – Bakuriu

答えて

1

getattr(A, 'a')は、クラスでも記述子プロトコルをトリガーするため、String.__get__(None, A)が呼び出されます。

String.__get__()メソッドに明示的なreturnステートメントがないため、Noneが返されます。 Descriptor Howtoから

クラスの場合は、機械がB.__dict__['x'].__get__(None, B)B.xを変換type.__getattribute__()です。

getattr(A, 'a')はここA.aのからわずかダイナミックなので、A.__dict__['x'].__get__(None, A)はあなたがA.__dict__['x']と同じものを取得しない理由である、実行されます。

ディスクリプタオブジェクト自体を返すと予想された場合は、を明示的にとする必要があります。 instanceは、その場合にはNoneに設定されます。

class String(object): 
    def __get__(self, instance, owner): 
     if instance is None: 
      return self 
    def __set__(self, instance, value): 
     pass 

これはproperty記述子オブジェクトが何をするかです。

descriptor.__get__へのownerの引数はオプションです。設定されていない場合は、代わりにtype(instance)を使用することになっています。

0

getattr(A, 'a')は、A.aと同じです。存在する場合、これはそれぞれの記述子を呼び出します。したがって、ディスクリプタによって提示される値はNoneです。

関連する問題