猿问

从Python的子类中删除属性

有什么方法可以从父类中存在的子类中删除属性?


在下面的例子中


class A(object):

    foo = 1

    bar = 2


class B(A):

    pass


# <desired code here>


b = B()

assert hasattr(b, 'bar') == False

我们可以编写任何代码来使断言通过吗?


DIEA
浏览 228回答 2
2回答

缥缈止盈

是的,使用描述符的魔力。请参阅我的博客文章。精简版:class nosubclasses(object):&nbsp; &nbsp; def __init__(self, f, cls):&nbsp; &nbsp; &nbsp; &nbsp; self.f = f&nbsp; &nbsp; &nbsp; &nbsp; self.cls = cls&nbsp; &nbsp; def __get__(self, obj, type=None):&nbsp; &nbsp; &nbsp; &nbsp; if type == self.cls:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if hasattr(self.f, '__get__'):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return self.f.__get__(obj, type)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return self.f&nbsp; &nbsp; &nbsp; &nbsp; raise AttributeError例子:In [2]: class MyClass(object):&nbsp; &nbsp;...:&nbsp; &nbsp; &nbsp;x = 1&nbsp; &nbsp;...:In [3]: MyClass.x = nosubclasses(MyClass.x, MyClass)In [4]: class MySubclass(MyClass):&nbsp; &nbsp;...:&nbsp; &nbsp; &nbsp;pass&nbsp; &nbsp;...:In [5]: MyClass.xOut[5]: 1In [6]: MyClass().xOut[6]: 1In [80]: MySubclass.x---------------------------------------------------------------------------AttributeError&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Traceback (most recent call last)<ipython-input-80-2b2f456dd101> in <module>()----> 1 MySubclass.x<ipython-input-51-7fe1b5063367> in __get__(self, obj, type)&nbsp; &nbsp; &nbsp; 8&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return self.f.__get__(obj, type)&nbsp; &nbsp; &nbsp; 9&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return self.f---> 10&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;raise AttributeErrorAttributeError:In [81]: MySubclass().x---------------------------------------------------------------------------AttributeError&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Traceback (most recent call last)<ipython-input-81-93764eeb9948> in <module>()----> 1 MySubclass().x<ipython-input-51-7fe1b5063367> in __get__(self, obj, type)&nbsp; &nbsp; &nbsp; 8&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return self.f.__get__(obj, type)&nbsp; &nbsp; &nbsp; 9&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return self.f---> 10&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;raise AttributeErrorAttributeError:但是,正如评论者@delnan指出的那样,这违反了Liskov可替换性原则。我的博客文章中的动机是有根据的,因为该属性未描述对象本身。但总的来说,这首先破坏了能够进行子类化的整个目的,而这实际上就是拥有类的全部要点。顺便说一下,我的答案和@jamylak的区别在于,在@jamylak的答案中,每个子类都删除了属性。如果您制作了class C(A),它仍将具有bar属性。在我的回答中,类本身(实际上是属性)不允许子类具有该属性,因此,一口气,所有子类都没有该属性。
随时随地看视频慕课网APP

相关分类

Python
我要回答