我正在尝试正确输入提示我的代码,并遇到了 Callable 和 FunctionType
from typing import Callable
def my_func() -> Callable:
f = lambda: _
return f
result = my_func()
type(result) # <class 'function'>
isinstance(result, Callable) # True
对
from types import FunctionType
def my_func() -> FunctionType
f = lambda: ...
return f
result = my_func()
type(result) # <class 'function'>
isinstance(result, FunctionType) # True
我能想到的一个可能的情况是区分常规可调用对象和基于类的可调用对象,如下所示
class C:
def __call__(self):
pass
def my_func() -> Callable:
c = C()
return c
result = my_func()
type(result) # <class 'function'>
isinstance(result, Callable) # True
isinstance(result, FunctionType) # False
它们之间有什么区别以及何时我必须使用其中一种而不是另一种?
types.FunctionType
在cpython/Lib/types.py#L11-L12中动态定义为最简单函数的类型。
def _f(): pass
FunctionType = type(_f)
另一方面,typing.Callable
被定义为包装的collections.abc.Callable
,如果使用python >= 3.9,则a)应该直接使用,b)本身在cpython/Lib/_collections_abc.py#L534中定义-L548 作为具有 __call__
方法的东西。
class Callable(metaclass=ABCMeta): # NOTE: I'm skipping most of the definition
@classmethod
def __subclasshook__(cls, C):
if cls is Callable:
return _check_methods(C, "__call__")
return NotImplemented
您已经正确地强调了几乎任何东西都可以是可调用的,只需要给它一个
__call__
方法,另一方面,类永远不会是函数。
在大多数情况下,您应该使用
Callable
,除非您完全确定您只需要一个函数。
此外,您可以(并且应该)键入
Callable
的参数和返回值,例如:
Callable[[], None]
-- 无参数,返回 None
(例如 lambda: None
)Callable[[int, int], int]
-- 两个 int
参数,返回一个 int
Callable[..., None]
-- 任何参数,返回 None
,(例如 print
)。