首页 > 解决方案 > 在抽象基类中定义 @property.setter 会产生 AttributeError

问题描述

一个抽象基类Base有一个@abstractmethod命名data,它也是一个@property.

问题:有没有办法data.setterBase类中定义属性setter,这样我们就不用在所有子类(即Foo)中重复定义setter方法了?

data.setter在 ABC 中定义时显示 AttributeError 的代码

from abc import ABC, abstractmethod

def reload_data():
    return ['hello']


class Base(ABC):
    @property
    @abstractmethod
    def data(self):
        pass

    @data.setter               # <----- AttributeError if this is defined here
    def data(self, value):
        self._data = value


class Foo(Base):
    def __init__(self):
        self._data = None

    @property
    def data(self):
        if self._data is None:
            self._data = reload_data()
        return self._data

    # @data.setter              # <----- Defining it here avoids AttributeError, but 
    # def data(self, value):             causes code repetition in all the subclasses of Base
    #     self._data = value

foo = Foo()
foo.data = ['world']
print(foo.data)

标签: pythonpython-3.xabc

解决方案


我不知道是否有办法用@property装饰器来做,但如下所示“手动”做似乎有效。

from abc import ABC, abstractmethod


def reload_data():
    return ['hello']


class Base(ABC):
    @abstractmethod
    def _get_data(self):
        pass

    # Non-abstract.
    def _set_data(self, value):
        self._data = value


class Foo(Base):
    def __init__(self):
        self._data = None

    # Define inherited abstract method.
    def _get_data(self):
        if self._data is None:
            self._data = reload_data()
        return self._data

    data = property(_get_data, Base._set_data)


foo = Foo()
foo.data = ['world']
print(foo.data)  # ['world']

推荐阅读