5

私はこのコードを持っています:

class A:
    def __init__(self):
        def method(self, item):
            print self, ": Getting item", item
        self.__getitem__ = types.MethodType(method, self, self.__class__)

class B(object):
    def __init__(self):
        def method(self, item):
            print self, ": Getting item", item
        self.__getitem__ = types.MethodType(method, self, self.__class__)

次に、これは正常に機能します。

a = A()
a[0]

しかし、これはしません:

b = B()
b[0]

TypeErrorを発生させます。

新しいスタイルのクラスは、インスタンス__dict__ではなくクラス__dict__で魔法のメソッドを探すことがわかりました。これは正しいですか?なんでそうなの?背後にある考え方を説明している記事を知っていますか?私はRTFMを試しましたが、おそらく正しいものではなかったか、物事を捕まえませんでした...

どうもありがとうございます!ポール

4

3 に答える 3

6

これは、Pythonデータモデルのドキュメントに記載されています:新しいスタイルのクラスの特別なメソッドルックアップ

新しいスタイルのクラスの場合、特別なメソッドの暗黙的な呼び出しは、オブジェクトのインスタンスディクショナリではなく、オブジェクトの型で定義されている場合にのみ正しく機能することが保証されます。

この動作の背後にある理論的根拠は、型オブジェクトを含むすべてのオブジェクトによって実装される、__hash__()などの多くの特別なメソッドにあります。__repr__()これらのメソッドの暗黙的なルックアップが従来のルックアッププロセスを使用した場合、タイプオブジェクト自体で呼び出されたときに失敗します[。]

したがって、とは両方とも機能する必要があるためhash(int) hash(1)インスタンスではなく型で特別なメソッドが検索されます。__hash__()オブジェクトを真っ直ぐに調べた場合、はhash(int)に変換されますint.__hash__()が、これは失敗します。これは、がバインドされていないメソッドであり、 (eg )int.__hash__()の実際のインスタンスで呼び出されることを想定しているためです。したがって、の場合は、代わりに呼び出す必要があります。int()1hash(int)type.__hash__()

>>> hash(1) == int.__hash__(1)
True
>>> hash(int) == type.__hash__(int)
True
>>> int.__hash__()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: descriptor '__hash__' of 'int' object needs an argument

これは後方互換性のない変更であるため、新しいスタイルのオブジェクトにのみ適用されます。

于 2012-12-31T14:08:22.550 に答える
0

特別なメソッドは、古いスタイルのクラスとは異なり、オブジェクトのクラスが新しいスタイルのクラスである場合にのみ、オブジェクトのクラスに対して検索されます。インスタンスでメソッドを定義し__getitem__ていますが、これは新しいスタイルのクラスでは効果がありません。

于 2012-12-31T13:59:56.763 に答える
0

__getitem__デフォルトのイテレータは、新しいスタイルクラスでは使用されません。例については、http: //grokbase.com/t/python/tutor/085k143q1r/new-style-classes-getitem-and-iterationを参照してください。Python2.2__getitem__と新しいスタイルのクラスでの動作が変更されたようです。

于 2012-12-31T14:08:04.193 に答える