python __annotations__ 来自@属性

python __annotations__ from @property

我想获取所有的注解,包括属性注解。 我得到的只是为常规注释设置的注释:

from dataclasses import dataclass

@dataclass
class Test:
    first: int = 1

    @property
    def second(self) -> int:
        return 5


t = Test()
print(t.__annotations__)
# prints: {'first': <class 'int'>}

有没有办法让 'second' 作为 __annotations__ 的一部分? 甚至可能将其强制为 __anotations__.

使用 __annotations__ 获取有关如何将数据 class 转换为 json 的信息似乎是个坏主意。它要么阻止您使用 InitVarClassVar 等瞬态属性,要么在您使用它们时导致不一致和错误的行为。您应该改用 __dataclass_fields__

话虽这么说,但有时您的用例足够简单,可以做到,或者您被无法轻易改进的第 3 方软件包之一锁定在其中,因此这是一种方法将数据class的__annotations__扩展到其属性中存在的那些:

class Test:
    var: int

    @property
    def x(self) -> int:
        return self.var + 2

    def __post_init__(self):
        cls = type(self)
        properties = [(x, getattr(cls, x)) for x in dir(cls) if type(getattr(cls, x)) == property]
        for name, property_ in properties:
            cls.__annotations__[name] = property_.fget.__annotations__["return"]

创建 Test 的实例现在将包含 属性,就像它是常规类型的属性一样:

>>> Test(1).__annotations__
{'var': <class 'int'>, 'x': <class 'int'>}

顺便说一句,__post_init__ 代码在每个实例的初始化期间执行,尽管严格来说它只需要在 class 生成时 运行 一次,因为 __annotations__ 是在 class 级别上定义的。因为它是幂等的,所以它不会破坏任何东西,但是 here 是一个更令人困惑但可以说更清晰的相同代码的应用程序,它也适用于常规 classes.