将types.FunctionType与typing.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
有好处吗?
答案 0 :(得分:1)
types
模块早于PEP 484注释,其创建主要是为了使对象的运行时内省更加容易。例如,要确定某个值是否为函数,可以运行isinstance(my_var, types.FunctionType)
。
typing
模块包含类型提示,这些提示专门用于协助诸如mypy之类的静态分析工具。例如,假设您要指示参数必须是一个接受两个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
的实例,而不是任意的可调用键,则至关重要。