You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中能否同时重写抽象属性的get/set访问器?

抽象类中重写@property的getter和setter问题

问题描述

尝试使用abc模块定义包含抽象getter和setter的抽象类C,子类D重写这两个访问器后,运行结果显示D.x的getter仍使用C的抽象实现。请问是写法有误,还是无法同时重写这两个抽象访问器?

代码示例

from abc import ABC, abstractmethod

class C(ABC):
    @property
    @abstractmethod
    def x(self):
        pass

    @x.setter
    @abstractmethod
    def x(self, val):
        pass

class D(C):
    @C.x.getter
    def x(self):
        pass

    @C.x.setter
    def x(self, val):
        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 0x1017af2e0> True
set <function C.x at 0x1017af380> True
del None None
D.x:
get <function C.x at 0x1017af2e0> True
set <function D.x at 0x1017af4c0> False
del None None

原因分析与解决方法

问题根源

你在子类D中使用@C.x.getter的写法是错误的。C.x是父类的property对象,调用它的getter方法生成新属性时,并没有正确替换父类的抽象getter实现——实际上这个操作复用了父类C中x的getter方法,导致D.x的getter仍然指向父类的抽象方法。

正确写法

在子类中重写带抽象访问器的property时,需要先通过@property装饰器定义子类自己的getter方法,再用@x.setter来定义setter方法,这样才能完全覆盖父类的抽象访问器。

修正后的代码如下:

from abc import ABC, abstractmethod

class C(ABC):
    @property
    @abstractmethod
    def x(self):
        pass

    @x.setter
    @abstractmethod
    def x(self, val):
        pass

class D(C):
    @property
    def x(self):
        # 子类自定义getter实现
        pass

    @x.setter
    def x(self, val):
        # 子类自定义setter实现
        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 0x1020b72e0> True
set <function C.x at 0x1020b7380> True
del None None
D.x:
get <function D.x at 0x1020b74c0> False
set <function D.x at 0x1020b7560> False
del None None

可以看到,D.x的getter和setter都已经替换为子类自己的实现,__isabstractmethod__均为False,符合预期。

内容的提问来源于stack exchange,提问作者М. Ю. Брызгалов

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 05:39:53