使用 types.FunctionType 与打字.Callable 的类型提示注释?

Mar*_*son 8 python type-hinting pycharm python-3.x

使用types.FunctionTypeTyping.Callable作为类型提示注释有何缺点或优点?

考虑下面的代码...

import types
import typing

def functionA(func: types.FunctionType):
    rt = func()
    print(func.__name__)
    return rt

def functionB(func: typing.Callable):
    rt = func()
    print(func.__name__)
    return rt
Run Code Online (Sandbox Code Playgroud)

我能看到的唯一区别是Callable可以是任何类型的可调用对象(函数、方法、类等),而FunctionType仅限于函数。
我是否忽略了什么?在某些情况下使用FunctionTypeover有好处吗?Callable

Mic*_*x2a 8

types模块早于 PEP 484 注释,其创建主要是为了使对象的运行时内省更加容易。例如,要确定某个值是否是函数,您可以运行isinstance(my_var, types.FunctionType).

typing模块包含专门用于协助静态分析工具(例如 mypy)的类型提示。例如,假设您要指示参数必须是接受两个 int 并返回 的函数str。你可以这样做:

def handle(f: Callable[[int, int], str]) -> None: ...
Run Code Online (Sandbox Code Playgroud)

没有办法以FunctionType类似的方式使用:它根本就不是为此目的而设计的。

这个函数签名也更灵活:它还可以接受诸如带有 a 的对象之类的东西__call__,因为这些对象确实是可调用的。

为了方便起见,模块的内容typing有时也可以以类似于 的内容的方式用于运行时检查types:例如,做isinstance(f, Callable)工作。然而,此功能被故意限制:isinstance(f, Callable[[int, int], str])故意禁止这样做。尝试执行该检查将在运行时引发异常。

也就是说,我认为使用以下任何内容执行运行时检查不是一个好的风格typing:该typing模块首先是用于静态分析的。

types出于类似的原因,我不会在类型提示中使用模块中的任何内容。唯一的例外是,如果您的函数以某种方式编写,那么您需要接收的值必须是 的具体实例FunctionType,而不是任意可调用的,这一点至关重要。

  • 那么“GeneratorType”呢,它只存在于“types”中,而不存在于“typing”中。我希望能够表明生成器正在返回,但不能仅通过“键入”来完成。或者我错过了什么? (2认同)