2 回答

TA貢獻2041條經驗 獲得超4個贊
是的,使用描述符的魔力。請參閱我的博客文章。精簡版:
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屬性。在我的回答中,類本身(實際上是屬性)不允許子類具有該屬性,因此,一口氣,所有子類都沒有該屬性。
添加回答
舉報