Да, с использованием магии 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's заключается в том, что в ответе @ jamylak атрибуты удаляются по каждому подклассу. Если вы сделали class C(A)
, у него все равно будет атрибут bar
. В моем ответе сам класс (ну, на самом деле атрибут) запрещает подклассы иметь атрибут, так что в одном махом все подклассы его не имеют.
Это нарушает принцип замещения Лискова. Другими словами, это ужасная идея, и B не должен быть подтипом A. – delnan
Мне просто интересно: для чего вы хотите это сделать? – cyroxx
@ delnan почему-то всякий раз, когда кто-нибудь упоминает, что я всегда думаю о [Ограничительном эффекте Блиновича] (http://en.m.wikipedia.org/wiki/Blinovitch_Limitation_Effect) от Doctor Who. –