我正在为我们内部的一些代码构建类型提示,但其中一部分在运行时是动态的。我试图让用户可以提前看到预期的类函数以帮助开发,但又不会强迫他们做很多额外的工作。
例如,给出这个通用示例:
target_dict = {"Example1": {"fcn1":fcn1, "fcn2":fcn2},
"Example2": {"fcn3":fcn3, "fcn4":fcn4}}
class Container:
def __init__(self, target: str):
for fcn_name, fcn in target_dict[target].items():
setattr(self, fcn_name, fcn)
def container_fcn(self):
pass
来电者:
x = Container("Example1")
y = Container("Example2")
这样,x 将是一个具有 fcn1 和 fcn2 的 Container 类,而 y 将是一个具有 fcn3 和 fcn4 的 Container 类。 我想要实现的目标是允许键入工具看到此动态功能,以便我的用户可以键入:
x = Container("Example1")
x.
并查看可作为自动完成/提示使用的
.container_fcn()
、.fcn1()
和 .fcn2()
选项。
需要注意的是,这些基本上是实际类的接口,因此即使我在这里定义了一个字典,它们也有一个实际的支持类,但我们有意不试图将它们作为子类引入。这意味着即使我将它们定义为字典条目,我也可以访问原始类以获取类型提示等内容。
这意味着我目前可以这样做来完成我想要的:
x: Union[Container, Example1]
y: Union[Container, Example2]
我想弄清楚的是是否可以跳过这个额外的步骤并允许类型库在初始化程序中使用字符串value作为类声明。
这个问题实际上可以归结为 PEP483、PEP484 等中定义的功能。我们在这里有一些灵活性,因此如果可以促进此功能,我们可以在不同的地方添加符号。最坏的情况,我只是依靠
Union
符号,但最终用户需要记住的东西越少越好。
您可以使用
@overload
和 Literal
键入每种呼叫类型。 Python 还没有类型映射,因此您需要手动输入每个可能的参数。
完整示例:
from typing import Any, Literal, overload, reveal_type
class Example1:
pass
class Example2:
pass
class Container:
@overload
def __new__(cls, target: Literal["Example1"]) -> Example1: ...
@overload
def __new__(cls, target: Literal["Example2"]) -> Example2: ...
def __new__(cls, *args, **kwargs) -> Any:
return super().__new__(cls, *args, **kwargs)
def __init__(self, target: str) -> None:
pass # TODO
ex1 = Container("Example1")
ex2 = Container("Example2")
reveal_type(ex1) # Type of "ex1" is "Example1"
reveal_type(ex2) # Type of "ex2" is "Example2"