简体   繁体   English

如何为返回自身的函数编写类型提示?

[英]How to write type hints for a function returning itself?

from typing import Callable


def f() -> Callable:
    return f

How to explicitly define f 's type?如何显式定义f的类型? like Callable[[], Callable]Callable[[], Callable]

I think it is slightly like a linked list, but I can't implement it.我觉得它有点像一个链表,但我无法实现它。

from typing import Union


class Node:
    def __init__(self, val):
        self.val = val
        self.next: Union[Node, None] = None

Ideally, you could use typing.Literal to specify the exact function being returned, but that doesn't work for a number of reasons:理想情况下,您可以使用typing.Literal来指定返回的确切函数,但由于多种原因,这不起作用:

  1. There's no way to refer to f using typing.Literal .没有办法使用typing.Literal来引用f typing.Literal['f'] is the string literal 'f' , not a forward reference to the function about to be defined. typing.Literal['f']是字符串文字'f' ,而不是对即将定义的函数的前向引用。

  2. f doesn't necessarily refer to the function being defined. f不一定是指正在定义的函数。 It's a free variable that could refer to something else entirely by the time the function is actually called.它是一个自由变量,可以在实际调用函数时完全引用其他内容。

OK, let's loosen our restriction.好的,让我们放宽限制。 Let's try to define a type of function that returns a function of its own type.让我们尝试定义一个函数类型,它返回一个它自己类型的函数。 We can at least write a valid type hint:我们至少可以写一个有效的类型提示:

T = typing.Callable[[],'T']

def f() -> T:
    return f

but this is only useful as documentation;但这仅作为文档有用; mypy doesn't yet know how to handle recursively defined types like this. mypy还不知道如何处理这样递归定义的类型。

So let's try所以让我们试试

T1 = Callable[[], 'T2']
T2 = Callable[[], T1]

def f() -> T2:
    return f

Oops, mypy doesn't like cyclic definitions, either.糟糕, mypy也不喜欢循环定义。

So we're left with your original idea, of using the overlay broad type of functions that take no arguments and returns some callable.因此,我们保留了您最初的想法,即使用覆盖范围广泛的不带参数并返回一些可调用函数的函数。

def f() -> Callable[[], Callable]:
    return f

The problem with the comparison to Node is that there's no type-level recursion involved;Node比较的问题是不涉及类型级递归; next simply refers to some value of type Node . next只是引用Node类型的某个值。

I think @chepner's answer is great.我认为@chepner 的回答很棒。 If you really do want to express this as a recursive Callable type, then you could restructure the function as a callable class and do something like this:如果您确实想将其表示为递归 Callable 类型,那么您可以将该函数重组为一个可调用类并执行如下操作:

from __future__ import annotations


class F:
    def __call__(self) -> F:
        return self


f = F()

You can test this with mypy to see that it maintains its type on future calls:您可以使用 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()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM