3
class Foo(object):
    __slots__ = ('a',)

class Bar(Foo):
    @property
    def a(self):
        return super(Bar, self).a

 super(Bar, Bar()).a = 4

このコードを使用している場合、これは機能しません。

>>> super(Bar, Bar()).a = 4
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'super' object has no attribute 'a'

なんで?

python docsによると、__slots__実装されています:

__slots__変数名ごとに記述子 (実装記述子) を作成することにより、クラス レベルで実装されます。その結果、クラス属性を使用して、によって定義されたインスタンス変数のデフォルト値を設定することはできません__slots__。そうしないと、クラス属性が記述子の割り当てを上書きします。

ただし、記述子は継承に対応できます (少なくとも純粋な python で記述されている場合)。

なぜこれが機能しないのか、誰かが知ってい__slots__ますか?

編集super():あなたが書き込もうとしている場合、記述子は一般的に で動作していないようです(ただし、読み取りは機能します)。したがって、私の質問は次のようになりsuper()ます。

4

1 に答える 1

4

super()記述子を返しません。記述子を取得した結果を返します。関数も返しません。バインドされたメソッドを返します。関数は記述子としても機能し、それらのメソッドはメソッドを返します。.__get__()

インスタンスaには定義されていないため、値はなく、記述子はAttributeErrorを発生させます。.__get__()

a次のインスタンスで定義すると、うまくいきますFoo

class Foo(object):
    __slots__ = ('a',)
    def __init__(self):
        self.a = 'spam'

したがって、__slots__値なしで記述子にアクセスすると、AttributeError:が発生します。

>>> class Foo(object):
...     __slots__ = ('a',)
... 
>>> Foo.a
<member 'a' of 'Foo' objects>
>>> Foo().a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: a
>>> Foo.a.__get__(Foo(), Foo)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: a

しかし、インスタンスに値を与えると、AttributeError消えます:

>>> class Foo(object):
...     __slots__ = ('a',)
...     def __init__(self):
...         self.a = 'spam'
... 
>>> Foo.a.__get__(Foo(), Foo)
'spam'

これsuper()で、記述子の結果を問題なく見つけることができます(clobberではない別の属性名でデモンストレーションしますself.a)。

>>> class Bar(Foo):
...     __slots__ = ('b',)
...     @property
...     def b(self):
...         return super(Bar, self).a
... 
>>> Bar().a
'spam'
于 2013-01-09T21:16:34.353 に答える