from typing import Callable
def f() -> Callable:
return f
如何显式定义f
的类型?如Callable[[], Callable]
我认为它有点像一个链表,但我无法实现它
from typing import Union
class Node:
def __init__(self, val):
self.val = val
self.next: Union[Node, None] = None
我认为@chepner的回答很好。如果您真的想将其表示为递归可调用类型,那么您可以将函数重新构造为可调用类,并执行以下操作:
from __future__ import annotations
class F:
def __call__(self) -> F:
return self
f = F()
你可以用mypy测试它,看看它在未来的调用中是否保持其类型:
g = f()
h = g(1) # Too many arguments for "__call__" of "F"
i = h()
j = i(2) # Too many arguments for "__call__" of "F"
k = j()
理想情况下,您可以使用typing.Literal
来指定返回的精确函数,但这不起作用,原因有很多:
-
使用
typing.Literal
无法引用f
。typing.Literal['f']
是字符串文字'f'
,而不是对即将定义的函数的前向引用。 -
f
不一定指正在定义的函数。它是一个自由变量,在实际调用函数时,它可能完全引用其他内容。
好吧,让我们放松限制。让我们尝试定义一种函数类型,它返回自己类型的函数。我们至少可以写一个有效的类型提示:
T = typing.Callable[[],'T']
def f() -> T:
return f
但这仅作为文档有用;mypy
还不知道如何处理像这样递归定义的类型。
所以让我们试试
T1 = Callable[[], 'T2']
T2 = Callable[[], T1]
def f() -> T2:
return f
糟糕的是,mypy
也不喜欢循环定义。
因此,我们只剩下您最初的想法,即使用覆盖广泛类型的函数,这些函数不带参数,并返回一些可调用的函数。
def f() -> Callable[[], Callable]:
return f
与Node
的比较问题在于不涉及类型级递归;next
简单地指Node
类型的一些值。