在下面的代码中,我创建了一个基本抽象类Base
。我希望从Base
继承的所有类都提供name
属性,因此我将此属性设为@abstractmethod
。
然后我创建了一个Base
的子类,名为Base_1
,它旨在提供一些功能,但仍然是抽象的。 name
中没有Base_1
属性,但是python会在没有错误的情况下设置该类的对象。如何创建抽象属性?
from abc import ABCMeta, abstractmethod
class Base(object):
__metaclass__ = ABCMeta
def __init__(self, strDirConfig):
self.strDirConfig = strDirConfig
@abstractmethod
def _doStuff(self, signals):
pass
@property
@abstractmethod
def name(self):
#this property will be supplied by the inheriting classes
#individually
pass
class Base_1(Base):
__metaclass__ = ABCMeta
# this class does not provide the name property, should raise an error
def __init__(self, strDirConfig):
super(Base_1, self).__init__(strDirConfig)
def _doStuff(self, signals):
print 'Base_1 does stuff'
class C(Base_1):
@property
def name(self):
return 'class C'
if __name__ == '__main__':
b1 = Base_1('abc')
答案 0 :(得分:45)
自Python 3.3修复了一个错误,意味着property()
装饰器现在在应用于抽象方法时被正确识别为抽象。
注意:订单很重要,您必须在@property
@abstractmethod
来自python docs:
class C(ABC):
@property
@abstractmethod
def my_abstract_property(self):
...
答案 1 :(得分:42)
在Python 3.3之前,您无法嵌套@abstractmethod
和@property
。
使用@abstractproperty
创建抽象属性(docs)。
from abc import ABCMeta, abstractmethod, abstractproperty
class Base(object):
# ...
@abstractproperty
def name(self):
pass
现在代码引发了正确的异常:
Traceback (most recent call last): File "foo.py", line 36, in b1 = Base_1('abc') TypeError: Can't instantiate abstract class Base_1 with abstract methods name
答案 2 :(得分:0)
基于上述詹姆斯的回答
def compatibleabstractproperty(func):
if sys.version_info > (3, 3):
return property(abstractmethod(func))
else:
return abstractproperty(func)
并将其用作装饰器
@compatibleabstractproperty
def env(self):
raise NotImplementedError()