I have the following code in Python:
class ModuleA:
    """This is a reusable element to compose larger designs with"""
class ModuleB:
    """Another reusable element"""
class MyDesign:
    a: ModuleA
    b0: ModuleB
    b1: ModuleB
    b2: ModuleB
The type hints are used upon instantiation of MyDesign to dynamically add instances of the various Modules. I chose this syntax because the class MyDesign is really just a “template” defining what Modules it’s composed of, but the instantiation of modules needs some arguments only available when MyDesign is being instantiated.
I would like to simplify the definition of MyDesign into something like
class MyDesign:
    a: ModuleA
# define repetitive patterns in a loop
for i in range(2):
    MyDesign.__type_hints__[f"b{i}"] = ModuleB
Is this possible?
Advertisement
Answer
Basically what you want is to dynamically modify the type hints in a class. You can achieve that by modifying the annotations__ property of the class like so:
from typing import get_type_hints
class ModuleA:
    """This is a reusable element to compose larger designs with"""
class ModuleB:
    """Another reusable element"""
class MyDesign:
    a: ModuleA
    b0: ModuleA
    b1: ModuleA
    b2: ModuleA
if __name__ == '__main__':
    print(get_type_hints(MyDesign))
    for i in range(2):
        MyDesign.__annotations__[f"b{i}"] = ModuleB
    print(get_type_hints(MyDesign))
result of running this code:
{'a': <class '__main__.ModuleA'>, 'b0': <class '__main__.ModuleA'>, 'b1': <class '__main__.ModuleA'>, 'b2': <class '__main__.ModuleA'>}
{'a': <class '__main__.ModuleA'>, 'b0': <class '__main__.ModuleB'>, 'b1': <class '__main__.ModuleB'>, 'b2': <class '__main__.ModuleA'>}
if you want to add the class members dynamically you can use this code:
for i in range(2):
    MyDesign.a = lambda: None
    setattr(MyDesign.a, f"b{i}", None)
    MyDesign.__annotations__[f"b{i}"] = ModuleB