types.FunctionType 与打字.Callable?

问题描述 投票:0回答:1

使用 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

我能看到的唯一区别是

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

python pycharm python-typing
1个回答
8
投票

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

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

def handle(f: Callable[[int, int], str]) -> None: ...

无法以类似的方式使用

FunctionType
:它根本不是为此目的而设计的。

这个函数签名也更灵活:它还可以接受带有

__call__
的对象,因为这些对象确实是可调用的。

为了方便起见,

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

也就是说,我认为使用

typing
中的任何内容执行运行时检查不是一个好的风格:
typing
模块首先用于静态分析。

出于类似的原因,我不会在类型提示中使用

types

 模块中的任何内容。唯一的例外是,如果您的函数的编写方式使得您需要接收的值特别是 
FunctionType
 的实例,而不是任意可调用的,这一点至关重要。

© www.soinside.com 2019 - 2024. All rights reserved.