抽象属性(不是属性)? [英] Abstract attribute (not property)?
问题描述
定义抽象实例属性而不是属性的最佳实践是什么?
What's the best practice to define an abstract instance attribute, but not as a property?
我想写一些类似的东西:
I would like to write something like:
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__
中).
Properties are handy, but for simple attribute requiring no computation they are an overkill. This is especially important for abstract classes which will be subclassed and implemented by the user (I don't want to force someone to use @property
when he just could have written self.foo = foo
in the __init__
).
Python 中的抽象属性 问题建议作为使用 @property<的唯一答案/code> 和
@abstractmethod
:它没有回答我的问题.
Abstract attributes in Python question proposes as only answer to use @property
and @abstractmethod
: it doesn't answer my question.
抽象类属性的 ActiveState 配方通过 AbstractAttribute
可能是正确的方法,但我不确定.它也仅适用于类属性而不适用于实例属性.
The ActiveState recipe for an abstract class attribute via AbstractAttribute
may be the right way, but I am not sure. It also only works with class attributes and not instance attributes.
推荐答案
如果你真的想强制子类定义一个给定的属性,你可以使用元类:
If you really want to enforce that a subclass define a given attribute, you can use metaclasses:
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 之后被调用.
Basically the meta class redefine __call__
to make sure check_bar
is called after the init on an instance.
GoodFoo() # ok
BadFoo () # yield NotImplementedError
这篇关于抽象属性(不是属性)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!