从根本上说,getter 和 setter 只是同一个类属性的一部分。在@propertyx 中,您有一个fget、fset 和fdel,它们组成了getter、setter 和deleter(不一定全部设置)。这些可能是抽象的并阻止初始化,或者根本不存在。
在您的class D 中,您创建了一个新的@property,它完全覆盖了父@property,因此不再有任何抽象设置器来阻止初始化类。
from abc import ABC, abstractmethod
class C(ABC):
@property
def x(self):
pass
@x.setter
@abstractmethod
def x(self, val):
pass
class D(C):
@property
def x(self):
pass
def examine_property(p):
print('get', p.fget, getattr(p.fget, '__isabstractmethod__', False) if p.fget is not None else None)
print('set', p.fset, getattr(p.fset, '__isabstractmethod__', False) if p.fset is not None else None)
print('del', p.fdel, getattr(p.fdel, '__isabstractmethod__', False) if p.fdel is not None else None)
print("C.x:")
examine_property(C.x)
print("D.x:")
examine_property(D.x)
输出:
C.x:
get <function C.x at 0x101ac4550> False
set <function C.x at 0x101ac45e0> True
del None None
D.x:
get <function D.x at 0x101ac4670> False
set None None
del None None
所以,如果你想覆盖 getter,你需要非常具体地使用 @C.x.getter:
class D(C):
@C.x.getter
def x(self):
print("non-abstract getter")
输出:
C.x:
get <function C.x at 0x1022fb550> False
set <function C.x at 0x1022fb5e0> True
del None None
D.x:
get <function D.x at 0x1022fb670> False
set <function C.x at 0x1022fb5e0> True
del None None
这样你就不会覆盖整个property,只覆盖它的特定功能。
我不会混合创建新的 properties 和覆盖父母,我在测试中看到了这种挑剔的行为:
class D(C):
@property
def x(self):
pass
@C.x.setter
def x(self, val):
pass
print("D.x:")
examine_property(D.x)
输出:
D.x:
get <function C.x at 0x10cdd74c0> False
set <function D.x at 0x10cdd7670> False
del None None
# Our new override property is gone
重新排序的类定义:
class D(C):
@C.x.setter
def x(self, val):
pass
@property
def x(self):
pass
输出:
D.x:
get <function D.x at 0x105048670> False
set None None
del None None
# We entirely lost the `setter`