当参数默认值由模块级别变量确定时,构成超载函数
我具有带有输入参数的Python函数,其值控制返回值的类型。可以省略参数(默认值 none ),在这种情况下,使用模块级别变量。这样,可以通过更改模块级别变量来更改默认行为。 最小示例:
from typing import overload, Union, Literal, Optional
option_default: Literal["str", "int"] = "int"
@overload
def test(option: Literal["str"]) -> str:
...
@overload
def test(option: Literal["int"]) -> int:
...
@overload
def test(option: Literal[None] = None) -> Union[str, int]:
...
def test(option: Optional[Literal["str", "int"]] = None) -> Union[str, int]:
if option is None:
option = option_default
if option == "str":
return "foo"
else:
return 1
foo: int = test() # Incompatible types in assignment (expression has type "Union[str, int]", variable has type "int")
option_default = "str"
baz: str = test() # Incompatible types in assignment (expression has type "Union[str, int]", variable has type "str")
通常,人们会使用typing.overload
来处理这种情况。但是,对于test()
,没有参数无法正常工作的参数,因此会出现mypy错误。这里有更好的方法在这里提供类型信息吗?
I have a Python function with an input parameter, the value of which controls the type of the return value. The parameter may be omitted (default value None
), in which case a module level variable is used. This way, the default behavior can be changed by changing the module level variable.
A minimal example:
from typing import overload, Union, Literal, Optional
option_default: Literal["str", "int"] = "int"
@overload
def test(option: Literal["str"]) -> str:
...
@overload
def test(option: Literal["int"]) -> int:
...
@overload
def test(option: Literal[None] = None) -> Union[str, int]:
...
def test(option: Optional[Literal["str", "int"]] = None) -> Union[str, int]:
if option is None:
option = option_default
if option == "str":
return "foo"
else:
return 1
foo: int = test() # Incompatible types in assignment (expression has type "Union[str, int]", variable has type "int")
option_default = "str"
baz: str = test() # Incompatible types in assignment (expression has type "Union[str, int]", variable has type "str")
Normally one would use typing.overload
to deal with this sort of situation. However, for test()
without arguments that doesn't work--hence the mypy errors. Is there a better way to provide type info here?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
那是不可能的。有 github上的建议 添加typescript的
typef
,但这是另一回事 - 它不会像您显示的那样跟踪可变变量。我认为即使在理论上也无法实施这样的功能。它为类型检查带来了许多新的复杂性。我可以想到一些有问题的方案:
现在
foo
保存了一个返回字符串的函数。您可以确定
value
的类型?无法保证some_other_module.baz()
未调用your_module.ints_are_the_bomb()
。因此,现在您需要跟踪所有可能发生在your_module.option_default
的更改,可能是跨模块的。如果客户端代码(如果是库)可以更改标志,那么这是不可能的。要概括,当您突变某些东西时,值(包括函数)的类型(包括函数)不会改变。这可能会破坏遥远的代码,而遥远的代码也恰好引用了此对象。
That's not possible. There is a proposal on GitHub to add
typeof
from TypeScript, but that's a different thing - it doesn't track mutable variables like you've shown.I don't think such a feature can be implemented, even in theory. It brings a lot of new complexity into type checking. I can think of some problematic scenarios:
Now
foo
has saved a function that returns a string.Can you be sure about the type of
value
? There's no guarantee thatsome_other_module.baz()
didn't callyour_module.ints_are_the_bomb()
. So now you need to track all changes that can ever happen toyour_module.option_default
, potentially across modules. And if client code (if this is a library) can change the flag, then it's just impossible.To generalize, the type of a value (including functions) can't change when you mutate something. That could break distant code that also happens to have a reference to this object.