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: float
annotation 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.bar
is 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.