What is the best way to look up the class from annotations if using py3.10
from __future__ import annotations? Previously,
self.__annotations__[name] would get you an object but now it returns a string. You can use
globals() as shown but that just doesn’t seem right to me. Is there a better way?
@dataclass class Person: height: float def stack(self, other: Person): return Person(self.height + other.height) #gymnasts @dataclass class Chair: height: float def stack(self, other: Chair): return Chair(0.6*(self.height + other.height) ) #stackable chairs @dataclass class Room: person: Person chair: Chair def set(self, name: str, val: float): # lots of complicated validation # factory = self.__annotations__[name] # this worked before from __future__ import annotations factory = globals()[self.__annotations__[name]] self.__setattr__(name, factory(height=val))
typing.get_type_hints to access the evaluated
__annotations__ of a “function, method, module or class object”. Notably, this is aware of basic inheritance – it merges inherited annotations and uses
globals of the current class instead of the method’s module.
@dataclass class Room: person: Person chair: Chair def set(self, name: str, val: float): factory = get_type_hints(type(self))[name] self.__setattr__(name, factory(height=val))
typing.get_type_hints does some additional work over just inspecting
__future__.annotations inherently erases non-global information. For the uncommon case of classes defined in a
locals scope one has to explicitly provide the namespace.