TypeVar('T')和Any的区别

5

假设我有一个通用的函数:

def foo(*args):
    for arg in args:
        print(arg)

如果我想给 *args 添加类型提示,根据PEP,我只需要指定一个参数的类型。

如果参数可以是任何类型,那该怎么办?下面两种方式有什么区别:

T = typing.TypeVar('T')

def foo(*args: T):
    ...

def foo(*args: Any):
    ...

据我所知,TypeVar('T') 相当于“任意类型”,但是在变量参数为多种类型时是否适用呢?

3
有了TypeVar,你可以建立类型之间的连接。只有TypeVar('T')本身只意味着与Any相同,def foo(*args: T) -> T表示foo返回与其输入相同的类型,这是无法用Any来表达的… - deceze
@deceze 如果返回 None,那么没有区别吗?如果是这样的话,我更喜欢使用 Any,因为对未来的读者来说它是不言自明的。 - user7811364
2
简短的回答是,如果您只在一个地方使用类型并且没有将其绑定,则使用TypeVar没有任何意义。 - Samwise
1个回答

4

有人可能会认为差别在于:

foo(*args: T) 表示函数可以接受任意数量的参数,这些参数可以是任何类型,但必须全都是相同的类型。

foo(*args: Any) 表示函数可以接受任意数量和任何类型的参数。

但实际上并非如此:https://github.com/python/mypy/issues/6559#issuecomment-473864640

实际上,这两个定义之间没有区别


关于你之前的观点,我认为这就是它的意思(任何类型都可以但仍然相同),但是例如调用foo('a', 1, ['a', 1])时,linter不会抛出错误。 - user7811364
@pasta_sauce 嗯,没错,mypy似乎不认为那是一个错误。要么我漏看了什么,要么这是个错误。 - ruohola
除非您以某种方式进一步缩小它(例如使用bound或在Generic中使用TypeVar,以便调用者可以缩小它),否则该类型可以是任意宽泛的。 如果您将“T”替换为“Union [str,int,List [Union [str,int]]]”,则上述用法将进行类型检查。 - Samwise
@Samwise 当然,但这并不是在这里被问到的。 - ruohola
@Samwise 这个例子可以通过类型检查,但这只是一个任意的例子,变量参数的类型和数量是未知的。 - user7811364
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接