【问题标题】:Defining @property.setter in Abstract Base Class gives AttributeError在抽象基类中定义 @property.setter 会产生 AttributeError
【发布时间】:2020-03-25 20:40:04
【问题描述】:

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

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

在 ABC 中定义 data.setter 时显示 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)

【问题讨论】:

  • @jonrsharpe 抱歉,我尝试阅读链接的文档,但缺乏了解如何将其应用于我的问题的知识。在这里的任何帮助将不胜感激!
  • 不需要太多的知识;它显示了一个正在应用的 setter,您只需要更改名称。
  • @jonrsharpe:遵循文档中的配方并不能解决问题。
  • 那么请给个minimal reproducible example

标签: python python-3.x abc


【解决方案1】:

我不知道是否有办法使用 @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']

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 2016-10-26
    • 1970-01-01
    • 2018-07-11
    • 1970-01-01
    • 2022-01-10
    相关资源
    最近更新 更多