【问题标题】:python __annotations__ from @propertypython __annotations__ 来自@property
【发布时间】:2021-06-28 08:17:19
【问题描述】:

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

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'>}

有没有办法将“第二”作为 __annotations__ 的一部分? 甚至可以强制它进入 __annotations__。

【问题讨论】:

  • 我认为这只会出现在属性 getter 本身 - Test.second.fget.__annotations__。上下文是什么,您打算如何使用注释?
  • 我继承自一个可以将对象保存为 json 的类,但它的工作方式是使用 __annotations__ 来确定从对象中保存的内容到 json 中。

标签: python oop python-dataclasses python-class


【解决方案1】:

使用__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 是一个更令人困惑但可以说是更干净的应用程序,它也适用于常规类。

【讨论】:

  • 太棒了。非常感谢!
猜你喜欢
  • 1970-01-01
  • 2013-11-17
  • 2021-05-27
  • 2021-04-14
  • 2010-11-23
  • 2021-12-22
  • 2012-09-06
  • 2021-07-21
  • 1970-01-01
相关资源
最近更新 更多