abc.abstractmethod + 属性
根据文档,将 @property
和 @abc.abstractmethod
结合使用应该是可行的,所以在python3.3中,下面的代码应该可以正常工作:
import abc
class FooBase(metaclass=abc.ABCMeta):
@property
@abc.abstractmethod
def greet(self):
""" must be implemented in order to instantiate """
pass
@property
def greet_comparison(self):
""" must be implemented in order to instantiate """
return 'hello'
class Foo(FooBase):
def greet(self):
return 'hello'
测试一下这个实现:
In [6]: foo = Foo()
In [7]: foo.greet
Out[7]: <bound method Foo.greet of <__main__.Foo object at 0x7f935a971f10>>
In [8]: foo.greet()
Out[8]: 'hello'
所以这显然不是一个属性,因为如果是属性的话,应该像这样工作:
In [9]: foo.greet_comparison
Out[9]: 'hello'
也许我太笨了,或者它根本就不行,有人有什么想法吗?
1 个回答
8
如果你想让 greet
成为一个属性,你还是需要在实现中使用 @property
装饰器。
class Foo(FooBase):
@property
def greet(self):
return 'hello'
ABC元类的作用就是检查你在具体类中是否提供了相同的名称;它不在乎这个名称是方法、属性还是普通的变量。
因为它不在乎,所以也不会自动应用 property
装饰器。这其实是个好事;因为在某些情况下,使用静态属性就足够满足需求,而使用属性可能就显得多余了。
ABC元类的目的是帮助你发现实现中的不足;它并不是用来强制规定属性的类型。
需要注意的是,在Python 3.3之前,你不能把 @property
和 @abstractmethod
一起使用。你需要使用一个叫 @abstractproperty
装饰器。在这种情况下,如果你的属性需要的不仅仅是一个简单的获取方法,就会有些模糊;而Python 3.3对此处理得更好(详细信息可以查看 问题11610)。