5

リンクから記述子がどのように機能するかの説明を読んでいます: http://users.rcn.com/python/download/Descriptor.htm#properties

しかし、ここでは、クラスProperty__get__メソッドの下で、メソッドの署名について疑問があります。メソッドのシグネチャは次のとおりです。

def __get__(self, obj, objtype=None):

objここで、が None または実際のオブジェクトになるタイミングと方法を知っています。

しかし、私は理解できませんでした:どのような場合objtypeNone? そして、それが実際の例でどのように役立つか。

4

5 に答える 5

6

署名

def __get__(self, obj, objtype=None):

objtypeそれはオプションの引数だと言っています。引数__get__を 1 つだけ指定して を呼び出すと、objtypeが に設定されNoneます。


たとえば、次のfoo.bazように定義することで、Foo は Bar からメソッドを盗むことができます。

class Foo(object):
    pass
class Bar(object):
    def baz(self):
        print('Hi')        

foo = Foo()
foo.baz = Bar.baz.__get__(foo)
print(foo.__dict__)
# {'baz': <bound method ?.baz of <__main__.Foo object at 0xb787006c>>}
foo.baz()
# Hi

代わりに、 の 2 引数形式__get__が使用された場合、

foo.baz = Bar.baz.__get__(foo, foo.__class__)

thenfoo.bazバインドされていないメソッドBar.bazであり、foo.baz()レイズします

TypeError: unbound method baz() must be called with Bar instance as first argument (got nothing instead)

Python3 では の概念unbound methodが削除されていることに注意してください。呼び出し元の obj のクラスが正しい型であることを確認するためのチェックはこれ以上ありません。そのため、Python3 では、1 引数形式と 2 引数形式の両方の定義foo.bazが機能します。

于 2012-09-30T11:56:26.407 に答える
2

おそらく私は上記の答えを言い換えていますが、上記の考えのこのプレゼンテーションは、私にとってより簡単に理解できるように思えました.

@cached_property のこの実装を検討してください

class cached_property(object):
    """Like @property, but caches the value."""

    def __init__(self, func):
        self._func = func

    def __get__(self, obj, cls):
        if obj is None:
            return self
        value = self._func(obj)
        obj.__dict__[self.__name__] = value
        return value

「なぜobjチェックされるのNoneですか?」に関して同じ質問がありました。と「なぜ自己を返すのですか?」

両方の状況がどのように発生するかの例を次に示します

典型的な使用法:

class Foo(object):
    @cached_property
    def foo(self):
        # Would usually have significant computation here
        return 9001

foo_instance = Foo()
foo_foo = foo_instance.foo # Behind the scenes invokes Foo.foo.__get__(foo_instance, Foo)

待って、ええ、これは私が期待していることobjですNone

あまり一般的ではない使用法 (プロパティのバインドされていないバージョンへのアクセスを取得する)

Foo上記と同じ)

>> Foo.foo
<__main__.cached_property at 0x178bed0>

この場合、呼び出しは次のようになりますFoo.foo.__get__(None, Foo)

于 2013-09-08T02:03:39.010 に答える
1

python docs では、これについてはImplementing Descriptorsで詳しく説明しています。署名は、実際に以下に提供されているものです。あなたが言及したように、インスタンスはおそらくNoneですが、所有者は決してNoneであってはなりません。読み方が間違っていたのかもしれません。

object.__get__(self, instance, owner)
于 2012-09-30T11:45:54.840 に答える
0

objtype は、obj の「所有者」クラスを表します。つまり、インスタンスを obj に渡し、その基本クラスを objtype に渡します。ただし、指定されたクラスのインスタンスが存在しない可能性があるため、obj は None になる可能性がありますが、objtype は AttributeError 例外が発生するため、None にすることはできません。マーワンが言ったように、あなたはそこに何かを混ぜていませんか? ;)

于 2012-09-30T11:48:18.067 に答える