type(param) 方法存在一些问题。
首先,正如 Oleh 在他的回答中提到的,所有注释在 函数定义时必须是有效的。在像您这样的示例中,您可能会因variable shadowing 而遇到问题。
param = 10
def f(param) -> type(param):
return param
f('a')
由于变量 param 的类型为int,因此函数的注释本质上读作f(param: Any) -> int。所以当你传入参数 param 的值为'a' 时,这意味着f 将返回一个str,这使得它与注解不一致。诚然,这个例子是人为的,但从语言设计的角度来看,这是需要小心的。
相反,正如 jonrsharpe 所提到的,引用 generic types 提到的参数(如 jonrsharpe)的最佳方式通常是使用 type variables。
这可以使用typing.TypeVar 类来完成。
from typing import TypeVar
def f(param: T) -> T:
return param
这意味着静态检查器不需要实际访问param 的类型,只需在检查时检查是否有办法同时考虑param 和相同类型的返回值。我说考虑相同的类型,因为您有时只会断言它们都实现相同的abstract base class/接口,例如numbers.Real。
然后可以在泛型类型中使用typevars
from typing import List, TypeVar
T = TypeVar('T')
def total(items: List[T]) -> List[T]:
return [f(item) for item in items]
使用类型变量和泛型会更好,因为它添加了额外的信息并允许更多的灵活性(如numbers.Real 的示例中所述)。例如,使用List[T] 的能力非常重要。在您使用type(param) 的情况下,它只会返回list,而不是像List[T] 那样的列表。所以使用type(param) 实际上会丢失信息,而不是添加它。
因此,最好还是坚持使用type variables 和generic types。
TL;DR:
- 由于variable shadowing,
type(param) 可能会导致注释不一致。
- 由于有时在考虑系统类型时,您会根据 接口(Python 中的 abstract base classes)而不是具体类型来考虑,因此最好依赖 ABC 和 @987654330 @
- 使用
type(param) 可能会丢失由泛型提供的信息。