我想说
def f(param) -> type(param): return param
但是我得到了NameError: name 'param' is not defined
。这里的关键是返回类型是函数参数的函数。我浏览了https://www.python.org/dev/peps/pep-3107/,但看不到任何有关有效注释表达式的精确描述。
我会接受一个答案,解释为什么现在完全是不可能的,即,它是否不适合当前的注释范例,或者这是否存在技术问题?
答案 0 :(得分:1)
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来引用参数type variables(如jonrsharpe)的最佳方法通常是使用abstract base class。
这可以使用typing.TypeVar
类来完成。
from typing import TypeVar
def f(param: T) -> T:
return param
这意味着静态检查器将不需要实际访问param
的类型,只需检查一下检查时是否有一种方法可以同时考虑param
和返回值。相同的类型。我说的是同一类型,因为有时您只会断言它们都实现了相同的numbers.Real
/接口,例如type variables。
然后可以在泛型类型中使用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)
实际上会丢失信息,而不是添加它。
因此,最好还是使用generic types和variable shadowing。
TL; DR :
type(param)
可能导致注释不一致。type(param)
可能会丢失通用信息会提供的信息。答案 1 :(得分:0)
让我们看一下https://122e4e-mapbox.global.ssl.fastly.net/mapbox-gl-js/example/polygon-popup-on-click/。
注释必须是有效的表达式,其值在定义函数时不会引起异常 (但有关正向引用,请参见下文)。
注释应保持简单,否则静态分析工具可能无法解释这些值。例如,动态计算的类型不太可能被理解。 (这是一个故意含糊的要求,经讨论保证,可以在此PEP的将来版本中添加特定的包含和排除。)
我想说您的方法很有趣,可能对静态分析很有用。但是,如果我们接受PEP作为当前注释范例解释的来源,则突出显示的文本将说明为什么在调用时无法动态定义返回类型的原因。