抽象属性(不是属性)?
定义抽象实例属性而不是属性的最佳实践是什么?
我想写一些像:
class AbstractFoo(metaclass=ABCMeta):
@property
@abstractmethod
def bar(self):
pass
class Foo(AbstractFoo):
def __init__(self):
self.bar = 3
代替:
class Foo(AbstractFoo):
def __init__(self):
self._bar = 3
@property
def bar(self):
return self._bar
@bar.setter
def setbar(self, bar):
self._bar = bar
@bar.deleter
def delbar(self):
del self._bar
属性很方便,但是对于不需要计算的简单属性来说,这太过分了。这对于将由用户进行子类化和实现的抽象类尤为重要(我不想强迫某人@property
只可以在中编写代码来使用self.foo
= foo
它__init__
)。
Python问题中的抽象属性仅建议使用@property
和的答案@abstractmethod
:它不能回答我的问题。
通过抽象类属性的ActiveState配方AbstractAttribute
可能是正确的方法,但是我不确定。它也仅适用于类属性,不适用于实例属性。
-
如果您确实想强制子类定义给定的属性,则可以使用元类。就我个人而言,我认为这可能是矫kill过正,不是很Python,但是您可以执行以下操作:
class AbstractFooMeta(type): def __call__(cls, *args, **kwargs): """Called when you call Foo(*args, **kwargs) """ obj = type.__call__(cls, *args, **kwargs) obj.check_bar() return obj class AbstractFoo(object): __metaclass__ = AbstractFooMeta bar = None def check_bar(self): if self.bar is None: raise NotImplementedError('Subclasses must define bar') class GoodFoo(AbstractFoo): def __init__(self): self.bar = 3 class BadFoo(AbstractFoo): def __init__(self): pass
基本上,重新定义元类
__call__
以确保check_bar
在实例的init之后被调用。GoodFoo() # ok BadFoo () # yield NotImplementedError