python __annotations__ 来自@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__ 的一部分? 甚至可能将其强制放入 __annotations__。

解决方法

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

话虽如此,有时您的用例很简单,可以做到,或者您被无法轻松改进的第 3 方软件包之一锁定在其中,因此这里是一种扩展数据类的 __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__ 代码在每个实例的初始化期间执行,尽管严格来说它只需要在类生成时运行一次,因为 __annotations__ 是在班级。由于它是幂等的,因此不会破坏任何内容,但 here 是一个更令人困惑但可以说更清晰的应用程序,同样的代码也适用于常规类。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...