Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
132 views
in Technique[技术] by (71.8m points)

Define Python type hints in for-loop inside class body

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?

question from:https://stackoverflow.com/questions/65883790/define-python-type-hints-in-for-loop-inside-class-body

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...