[英]How can I type hint a variable whose Union type gets narrowed in Python?
I have a few helper functions that get passed a type converter and a value.我有一些辅助函数可以传递一个类型转换器和一个值。 Based on checks that happen later, I decide which helper function to call.
根据稍后发生的检查,我决定调用哪个助手 function。
How can I correctly annotate the types to narrow the foo
variable's type below so that it can pass a mypy
check?如何正确注释类型以缩小下面的
foo
变量的类型,以便它可以通过mypy
检查?
from typing import Type, Union
def do_something(
typ: Type[Union[float, int]],
bar: Union[float, int]
) -> Union[float, int]:
return bar
foo: Type[Union[float, int, str]] = float
assert foo is float or foo is int
do_something(foo, 4.4)
Bonus points if the solution can ensure that typ
is a converter to the type of bar
!如果解决方案可以确保
typ
是bar
类型的转换器,则加分!
Well, here's something that works, but maybe there's a better way without a cast:好吧,这里有一些可行的方法,但也许没有演员表有更好的方法:
from typing import Type, Union, cast
def do_something(
typ: Type[Union[float, int]],
bar: Union[float, int]
) -> Union[float, int]:
return bar
foo: Type[Union[float, int, str]] = float
assert foo is float or foo is int
do_something(cast(Type[float], foo), 4.4)
The tool you want here is a TypeVar .您在这里需要的工具是TypeVar 。
Essentially, a TypeVar let's you say "I don't know quite what type this is (although I may have some ideas), but it'll be the same one throughout its use in this function."本质上,TypeVar 让你说“我不太清楚这是什么类型(尽管我可能有一些想法),但在 function 中的整个使用过程中,它都是同一个类型。” (or in some cases throughout its use in a class)
(或者在某些情况下,它在一个类中的整个使用过程中)
For example, this ensures that each thing you had a Union for gets the same value on any given call to the function.例如,这可确保您拥有 Union 的每个事物在对 function 的任何给定调用中都获得相同的值。
from typing import Type, TypeVar
# Define a type variable
# and list the things it is allowed to represent
NumberType = TypeVar("NumberType", int, float)
def do_something(
typ: Type[NumberType],
bar: NumberType
) -> NumberType:
return bar
This can be legally called with do_something(float, 2.5)
in which case it will return a float, or it can be called with do_something(int, 2)
in which case it will return an int.这可以合法地用
do_something(float, 2.5)
调用,在这种情况下它将返回一个浮点数,或者它可以用do_something(int, 2)
调用,在这种情况下它将返回一个 int。 That is, it makes sure that all the things match.也就是说,它确保所有的东西都匹配。
Because you called it a type converter, I suspect that you may not actually want all the types to match.因为您将其称为类型转换器,所以我怀疑您实际上可能并不希望所有类型都匹配。 If you need to constrain on more than one Type Variable, you can do so with something more like
如果您需要约束多个类型变量,则可以使用类似
from typing import Callable, TypeVar
# Define a type variable
# and list the things it is allowed to represent
NumberTypeIn = TypeVar("NumberTypeIn", int, float)
NumberTypeOut = TypeVar("NumberTypeOut", int, float)
def do_something(
converter: Callable[[NumberTypeIn], NumberTypeOut],
bar: NumberTypeIn
) -> NumberTypeOut:
return type_(bar)
As to the original question of narrowing unions of Type[]
s, as you've noticed is
doesn't work.至于缩小
Type[]
的联合的原始问题,正如您所注意到的那样is
行不通的。 Instead you can use issubclass
, as in相反,您可以使用
issubclass
,如
assert not issubclass(foo, str)
or或者
assert issubclass(foo, int) or issubclass(foo, float)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.