3

In Python 3.7, static fields can be annotated with the following syntax defined in PEP 526:

class A:
   foo: int

How can I make these annotations later on, after the class is defined? I would expect the following to work:

A.bar : float

However, it doesn't seem to have an identical effect to the first code. When we look at A's __dict___, those two snippets don't have the same effect.

After example 1 and after example 2, we get identical __dict__'s, i.e. the second example must show effect somewhere else. The dict created is:

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

I don't think editing __annotations__ is a "good" method of achieving what I want, especially because I'm not sure if it's the only case where foo is registered.

What is the proper way to do this?

4

1 回答 1

3

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

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

A.__annotations__['bar'] = float

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

请参阅PEP 526 - Syntax for Variable Annotations类型注释的运行时影响部分,该文档定义了此语法:

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

并来自Python 参考文档的带注释的赋值语句部分:

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

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

于 2018-10-08T09:06:39.140 回答