如何在 Python 中创建抽象缓存属性?

lmi*_*asf 6 python abc python-3.x

为了在 Python 中创建抽象属性,可以使用以下代码:

from abc import ABC, abstractmethod

class AbstractClassName(ABC):

    @cached_property
    @abstractmethod
    def property_name(self) -> str:
        pass


class ClassName(AbstractClassName):

    @property
    def property_name(self) -> str:
        return 'XYZ'


>>> o = AbstractClassName()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class AbstractClassName with abstract method property_name
>>> o = ClassName()
>>> o.property_name
'XYZ'
Run Code Online (Sandbox Code Playgroud)

这是我所期望的。我想创建一个抽象的缓存属性,所以我尝试了以下操作:

from abc import ABC, abstractmethod
from functools import cached_property


class AbstractClassName(ABC):

    @cached_property
    @abstractmethod
    def property_name(self) -> str:
        pass


class ClassName(AbstractClassName):

    @cached_property
    def property_name(self) -> str:
        return 'XYZ'

Run Code Online (Sandbox Code Playgroud)

然而,这并没有像我预期的那样工作:

>>> o = AbstractClassName()
>>> o.property_name
>>> o = ClassName()
>>> o.property_name
'XYZ'
Run Code Online (Sandbox Code Playgroud)

请注意,这次它允许我创建抽象类的实例AbstractClassName。我正在使用Python 3.10。有什么方法可以定义抽象缓存属性吗?

phi*_*phi 1

这是一个可能的解决方案

from abc import ABC, abstractmethod
from functools import cached_property


class AbstractClassName(ABC):
    @cached_property
    def property_name(self) -> str:
        return self._property_name()

    @abstractmethod
    def _property_name(self) -> str:
        ...


class ClassName(AbstractClassName):
    def _property_name(self) -> str:
        print("Heavy calculation")
        return "XYZ"
Run Code Online (Sandbox Code Playgroud)

测试

AbstractClassName()
# raise

a = ClassName()
print(a.property_name)
print(a.property_name)
# Heavy calculation
# XYZ
# XYZ
Run Code Online (Sandbox Code Playgroud)