【问题标题】:How to inject class-variable annotations in Python 3.7+?如何在 Python 3.7+ 中注入类变量注释?
【发布时间】:2018-10-08 09:01:04
【问题描述】:

在 Python 3.7 中,静态字段可以使用 PEP 526 中定义的以下语法进行注释:

class A:
   foo: int

在定义类之后,我以后如何进行这些注释?我希望以下工作:

A.bar : float

但是,它似乎与第一个代码的效果不同。当我们查看A__dict___ 时,这两个sn-ps 的效果并不相同。

在示例 1 之后 在示例 2 之后,我们得到相同的 __dict__,即第二个示例必须在其他地方显示效果。创建的字典是:

>> pprint(A.__dict__):
mappingproxy({'__annotations__': {'foo': <class 'int'>}, # <-!
              '__dict__': <attribute '__dict__' of 'A' objects>,
              '__doc__': None,
              '__module__': '__main__',
              '__weakref__': <attribute '__weakref__' of 'A' objects>})

我不认为编辑__annotations__ 是实现我想要的“好”方法,尤其是因为我不确定这是否是注册foo 的唯一情况。

这样做的正确方法是什么?

【问题讨论】:

    标签: python class python-3.7 type-annotation


    【解决方案1】:

    实例和类属性等变量注释中使用的信息存储在类上的__annotations__ 映射中,这是一个可写的字典。

    如果您想添加存储在那里的信息,那么只需将您的新信息直接添加到该映射:

    A.__annotations__['bar'] = float
    

    A.bar: float 注释被 Python丢弃,因为没有专门的位置来存储 annotated expressions 的信息;由静态类型检查器实现来决定该表达式是否有意义。

    请参阅PEP 526 -- Syntax for Variable AnnotationsRuntime Effects of Type Annotations section,定义此语法的文档:

    此外,在模块或类级别,如果被注释的项目是简单名称,那么它和注释将存储在该模块或类的__annotations__ 属性中( mangled if private) 作为从名称到评估注释的有序映射。

    以及来自 Python 参考文档的Annotated assignment statements section

    对于作为赋值目标的简单名称,如果在类或模块范围内,注释会被评估并存储在特殊的类或模块属性__annotations__ 中,这是一个从变量名(如果是私有的,则被破坏)到评估的注释的字典映射。该属性是可写的,并且在类或模块主体执行开始时自动创建,如果以静态方式找到注释。

    A.bar不是简单的名字,是表达式,所以不存储;如果您想在 __annotations__ 映射中保留该信息以供运行时访问,那么手动设置它是唯一的选择。

    【讨论】:

    • 谢谢!学Python的时候好像没用心学PEP^^
    • @Nearoo:实际上,在 Python 参考文档中也正确记录了带注释的赋值语句。
    • 嗯。永远不要通读文档。他们现在下线了,所以我无法检查。虽然它们真的很难导航,但如果不阅读整个主题,我很少会找到这样具体的知识。
    猜你喜欢
    • 2018-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-22
    相关资源
    最近更新 更多