有没有办法从父类中存在的子类中删除属性?
在以下示例中
class A(object):
foo = 1
bar = 2
class B(A):
pass
# <desired code here>
b = B()
assert hasattr(b, 'bar') == False
我们可以编写任何代码来使断言通过吗?
答案 0 :(得分:5)
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
答案 1 :(得分:0)
是的,使用descriptors的魔力。请参阅我的blog post。简短版本:
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指出的那样,这违反了利斯科夫的可替代性原则。我的博客文章的动机是有保证的,因为该属性没有描述对象本身。但总的来说,这首先打破了能够进行子类化的重点,这实际上是完全拥有类的重点。
顺便说一下,我的答案和@jamylak之间的区别在于,在@jamylak的答案中,属性是基于每个子类删除的。如果您创建了class C(A)
,则它仍然具有bar
属性。在我的回答中,类本身(实际上是属性)不允许子类具有该属性,因此,一下子,所有子类都没有它。