2

クラシック クラスと新しいスタイル クラスの次の違いを考慮してください。

   class A():
        data = 'abcd'
        def __getattr__(self, name): 
            return getattr(self.data, name)

    class B(object):
        data = 'abcd'
        def __getattr__(self, name): 
            return getattr(self.data, name)



    print(A()[0])       # Prints 'a'
    print(B()[0])       # TypeError: 'B' object does not support indexing

このプロパティの説明は、新しいスタイル オブジェクトの属性検索が、組み込み操作のインスタンスではなくクラスで開始されるということです。しかし、クラスオブジェクトにも __getattr__ が定義されており、なぜここで欠落している属性 __getitem__ に対して呼び出されないのですか?

4

2 に答える 2

1

@Jon がコメントで言及しているように、 Asymmetric behavior for __getattr__, newstyle vs oldstyle classesの質問と、 Special method lookup for new-style classesのドキュメントで答えを見つけることができます。

特別なメソッドは、パフォーマンス上の理由から、クラス オブジェクトで直接検索されます。

私が知る限り、これはすべての非特別なメソッドをカプセル化されたクラスに転送できる一方で、__getattr__すべての特別なメソッドを明示的に転送する必要があることを意味します。

class A():
    data = 'abcd'
    def __getattr__(self, name): 
        return getattr(self.data, name)

class B(object):
    data = 'abcd'
    # forward all non-special methods to data
    def __getattr__(self, name): 
        return getattr(self.data, name)
    # forward __getitem__ to data
    def __getitem__(self, index):
        return self.data[index]


print(A()[0])       # Prints 'a'
print(B()[0])       # explicitly defined Prints 'a'
print(B().join([' 1 ',' 2 ']))  # forwarded to data prints ' 1 abcd 2 '

B.dataまた、インスタンス属性ではなくクラス属性であることも指摘したいと思います。この例では問題ありませんが、意図したものではない可能性があります。

于 2014-03-02T18:32:07.547 に答える