親に存在するサブクラスから属性を削除する方法はありますか?
次の例では
class A(object):
foo = 1
bar = 2
class B(A):
pass
# <desired code here>
b = B()
assert hasattr(b, 'bar') == False
アサーションをパスさせるために記述できるコードはありますか?
親に存在するサブクラスから属性を削除する方法はありますか?
次の例では
class A(object):
foo = 1
bar = 2
class B(A):
pass
# <desired code here>
b = B()
assert hasattr(b, 'bar') == False
アサーションをパスさせるために記述できるコードはありますか?
class A(object):
foo = 1
bar = 2
class B(A):
@property
def bar(self):
raise AttributeError
>>> b = B()
>>> b.bar
Traceback (most recent call last):
File "<pyshell#17>", line 1, in <module>
b.bar
File "<pyshell#15>", line 4, in bar
raise AttributeError
AttributeError
はい、記述子の魔法を使用します。それについては私のブログ記事を参照してください。短縮版:
class nosubclasses(object):
def __init__(self, f, cls):
self.f = f
self.cls = cls
def __get__(self, obj, type=None):
if type == self.cls:
if hasattr(self.f, '__get__'):
return self.f.__get__(obj, type)
return self.f
raise AttributeError
例:
In [2]: class MyClass(object):
...: x = 1
...:
In [3]: MyClass.x = nosubclasses(MyClass.x, MyClass)
In [4]: class MySubclass(MyClass):
...: pass
...:
In [5]: MyClass.x
Out[5]: 1
In [6]: MyClass().x
Out[6]: 1
In [80]: MySubclass.x
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-80-2b2f456dd101> in <module>()
----> 1 MySubclass.x
<ipython-input-51-7fe1b5063367> in __get__(self, obj, type)
8 return self.f.__get__(obj, type)
9 return self.f
---> 10 raise AttributeError
AttributeError:
In [81]: MySubclass().x
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-81-93764eeb9948> in <module>()
----> 1 MySubclass().x
<ipython-input-51-7fe1b5063367> in __get__(self, obj, type)
8 return self.f.__get__(obj, type)
9 return self.f
---> 10 raise AttributeError
AttributeError:
しかし、コメント投稿者の @delnan が指摘したように、これは Liskov の代用可能性の原則に違反しています。属性がオブジェクト自体を説明していないため、私のブログ投稿の動機は正当なものでした。しかし、一般的に、これはそもそもサブクラス化できるという全体的なポイントを壊します。これは、クラスを持つことの実際の全体的なポイントです。
ちなみに、私の答えと@jamylakの答えの違いは、@jamylakの答えでは、サブクラスごとに属性が削除されることです。を作成した場合class C(A)
、属性は引き続き保持されbar
ます。私の答えでは、クラス自体 (実際には属性) は、サブクラスが属性を持つことを許可しないため、一挙にすべてのサブクラスがそれを持たなくなります。