使用摘要 getter 创建 属性 未按预期工作

Creating property with abstract getter doesn't work as expected

我正在尝试在摘要 class 上创建一个 属性。我没有将 @property 堆叠在 getter 之上的 @abstractmethod 之上,而是尝试在抽象基础 class 中手动创建 属性 getter 作为输入,我用 @abstractmethod.

装饰了它

使用前一种方法,您需要在子class 中再次用@property 修饰getter。而后一种方法对我来说稍微好一点,因为现在 subclass only 需要定义一个 getter 方法并且访问 属性 应该可以工作。但是,它似乎没有按预期工作。

import abc

class Foo(abc.ABC):
    @abc.abstractmethod
    def _get_bar(self) -> bool:
        ...

    # not preferred.
    # @property
    # @abc.abstractmethod
    # def BAR(self) -> bool:
    #     ...

    # works!
    # @property
    # def BAR(self) -> bool:
    #     return self._get_bar()

    # doesn't work!
    BAR = property(_get_bar)

class FooBar(Foo):
    # not preferred.
    # @property
    # def BAR(self) -> bool:
    #     ...

    def _get_bar(self) -> bool:
        return True

print(FooBar().BAR)  # TypeError: Can't instantiate abstract class FooBar with abstract methods BAR

我的依据是文档中关于 @abc.abstractmethod 的内容,即代码片段的最后一位。或者至少我认为我是。但是看起来我做错了什么或者没有很好地理解属性。

不同的是这段代码

BAR = property(_get_bar)

只在你的基础 class (Foo) 的主体被执行时执行一次 - 这个表达式中的_getbar指的是thisclass(Foo)中定义的方法,抽象空洞

虽然表格

@property
def BAR(self) -> bool:
    return self._get_bar()

将对 _get_bar 的引用封装在一个方法 (BAR) 中,该方法将接收实例作为参数,然后从 Foo 的任何子 class 中检索该方法实例 (self) 恰好是。

解决这个问题的方法是将函数调用形式中的 属性 参数包装为 lambda,以便在调用时从适当的 class 检索该方法:

BAR = property(lambda self: self._get_bar())