如何在类型提示中指定函数类型?

Posted

技术标签:

【中文标题】如何在类型提示中指定函数类型?【英文标题】:How can I specify the function type in my type hints? 【发布时间】:2016-10-16 13:17:01 【问题描述】:

我想在我当前的 Python 3.5 项目中使用类型提示。我的函数应该接收一个函数作为参数。

如何在类型提示中指定类型函数?

import typing

def my_function(name:typing.AnyStr, func: typing.Function) -> None:
    # However, typing.Function does not exist.
    # How can I specify the type function for the parameter `func`?

    # do some processing
    pass

我检查了PEP 483,但在那里找不到函数类型提示。

【问题讨论】:

一个函数是Callable python.org/dev/peps/pep-0483/#fundamental-building-blocks,“我们可能会添加”之前的最后一个要点。 【参考方案1】:

正如@jonrsharpe 在评论中指出的那样,这可以通过typing.Callable 完成:

from typing import AnyStr, Callable

def my_function(name: AnyStr, func: Callable) -> None:

问题是,Callable 本身被翻译成Callable[..., Any],这意味着:

可调用对象接受任意数量/类型的 个参数并返回任意类型的值。在大多数情况下,这不是您想要的,因为您将允许传递几乎任何函数。您还希望函数参数和返回类型也被提示。

这就是为什么typing 中的许多types 已被重载以支持表示这些额外类型的子脚本。因此,例如,如果您有一个函数 sum,它接受两个 ints 并返回一个 int

def sum(a: int, b: int) -> int: return a+b

你的注释是:

Callable[[int, int], int]

即参数在外订阅中下标,返回类型为外订阅中的第二个元素。一般来说:

Callable[[ParamType1, ParamType2, .., ParamTypeN], ReturnType]

【讨论】:

这个typing 的东西将整个python 语言提升了一个档次。 @javadba - 哦,是的,但我仍然不确定在哪个拨号上......顺便说一下 - Callable[[Arg, Types, Here], ...] 对于*args**kwargs,仅关键字 args 怎么样和位置只有参数?他们有没有想过在可调用对象的类型签名中调用约定? ;) According to the docs, typing.Callable 似乎赞成collections.abc.Callable【参考方案2】:

另一个值得注意的有趣点是,您可以使用内置函数type() 来获取内置函数的类型并使用它。 所以你可以有

def f(my_function: type(abs)) -> int:
    return my_function(100)

或者类似的东西

【讨论】:

类型提示可以是任何你想要的,但它们并不总是被懒惰地评估。另外,你的函数真的只取builtin_function_or_methodmy_function 吗? lambda 不工作吗?用户定义的函数或绑定方法? 一种非常聪明的方法,至少用于故障排除或头脑风暴 不,你不能,在运行mypy 时,会出现错误:error: Invalid type comment or annotation note: Suggestion: use type[...] instead of type(...)【参考方案3】:

一个最简单和花哨的解决方案是:

def f(my_function: type(lambda x: None)):
    return my_function()

这可以通过以下方式证明:

def poww(num1, num2):
    return num1**num2
    
print(type(lambda x: None) == type(poww))

输出将是: True

【讨论】:

这种注解类型的方式不包含任何关于签名的信息:参数数量、这些参数的类型、返回值类型。可以像这样注释函数类型,但我不推荐它。正如其他答案中所建议的那样,最好使用typing.Callable 来代替【参考方案4】:

我想要这个功能的具体用例是在 PyCharm 中启用丰富的代码完成。在这种情况下,使用 Callable 不会导致 PyCharm 建议该对象具有 .__code__ 属性,这正是我想要的。

我偶然发现了types 模块和..

from types import FunctionType

允许我用 FunctionType 注释对象,瞧,PyCharm 现在建议我的对象具有 .__code__ 属性。

OP 不清楚为什么这种类型的提示对他们有用。 Callable 当然适用于实现.__call__() 的任何东西,但为了进一步说明接口,我提交了types 模块。

可惜 Python 需要两个非常相似的模块。

【讨论】:

相反,vscode 中的 Pylance 仅接受 Callable 而不是 FunctionType 有效。

以上是关于如何在类型提示中指定函数类型?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 TypeScript 中指定定义为对象文字的箭头函数的类型?

如何在 c# dllimport 中指定 c++ Variant 返回类型

在 C 中指定枚举类型的大小

为啥我们需要在 bindParam() 中指定参数类型?

pandas使用select_dtypes函数移除dataframe中指定数据类型的数据列(exclude columns based on the data type in dataframe)

FindResource函数错误代码:1813-找不到映像文件中指定的资源类型 与LoadResource函数错误代码:1812-指定的映像文件不包含资源区域