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?
The information used in variable annotations for instance and class attributes is stored in the
__annotations__mapping on the class, a dictionary that's writable.If you want to add to the information stored there, then just add your new information directly to that mapping:
The
A.bar: floatannotation is discarded by Python, as there is no dedicated location to store the information for annotated expressions; it is up to the static type checker implementation to decide if that expression has meaning.See the Runtime Effects of Type Annotations section of PEP 526 -- Syntax for Variable Annotations, the document that defines this syntax:
and from the Annotated assignment statements section of the Python reference documentation:
A.baris not a simple name, it is an expression, so it is not stored; if you want to retain that information in the__annotations__mapping for runtime access, then manually setting it is the only option.