gpt4 book ai didi

python - 使用@abstractproperty 和@abstractmethod 实现/覆盖的实际差异

转载 作者:太空狗 更新时间:2023-10-30 01:02:40 25 4
gpt4 key购买 nike

考虑一个带有函数的抽象基类,您希望每个后续子类都覆盖该函数。使用 abc 模块和 ABCMeta;使用@abstractproperty@abstractmethod 进行装饰实际上会强制子类/开发人员实现创建装饰器指定的函数类型吗?根据我的实验,您可以使用子类中的方法覆盖抽象属性和使用属性覆盖抽象方法。

这个概念不正确吗?

最佳答案

这个概念是正确的; ABCMeta 代码不区分 abstractpropertyabstractmethod

这两个装饰器都为被装饰的项目添加了一个属性,.__isabstractmethod__ABCMeta 使用它来添加一个.__abstractmethods__ 属性(a frozenset) 到您定义的 ABC。 object 类型然后防止创建任何类的实例,其中 .__abstractmethods__ 中列出的任何名称没有具体实现。那里没有对功能与属性进行检查。

举例说明:

>>> from abc import *
>>> class C:
... __metaclass__ = ABCMeta
... @abstractmethod
... def abstract_method(self): pass
... @abstractproperty
... def abstract_property(self): return 'foo'
...
>>> C.__abstractmethods__
frozenset(['abstract_method', 'abstract_property'])

通过在子类中为它们创建新的覆盖,ABCMeta 类将使用 找到更少的方法或属性。 __isabstractmethod__ 属性,从而使生成的 __abstractmethods__ 设置更小;一旦集合为空,您就可以创建此类子类的实例。

这些检查是在 ABCMeta.__new__ constructor 中进行的并且不进行匹配描述符类型的检查:

cls = super(ABCMeta, mcls).__new__(mcls, name, bases, namespace)
# Compute set of abstract method names
abstracts = set(name
for name, value in namespace.items()
if getattr(value, "__isabstractmethod__", False))
for base in bases:
for name in getattr(base, "__abstractmethods__", set()):
value = getattr(cls, name, None)
if getattr(value, "__isabstractmethod__", False):
abstracts.add(name)
cls.__abstractmethods__ = frozenset(abstracts)

您必须创建一个 ABCMeta 的子类来覆盖 __new__ 方法,并检查在基类上命名的任何抽象方法或属性是否确实与cls 上的非抽象方法或属性。

关于python - 使用@abstractproperty 和@abstractmethod 实现/覆盖的实际差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14441619/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com