【问题标题】:Using type hint annotation using types.FunctionType vs typing.Callable?使用 types.FunctionType 与 typing.Callable 的类型提示注释?
【发布时间】:2019-09-16 07:09:13
【问题描述】:

使用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 有什么好处吗?

【问题讨论】:

  • 你的功能需要什么?可调用对象,还是由函数定义创建的类型的实例?
  • 声明任何符合您实际要求的类型。

标签: python python-3.x pycharm type-hinting


【解决方案1】:

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

typing 模块包含专门用于辅助静态分析工具(例如 mypy)的类型提示。例如,假设您要指示参数必须是一个接受两个整数并返回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 的一个实例,而不是任意可调用的,这一点至关重要。

【讨论】:

  • 我同意在运行时使用类型不是一个好主意。我不太相信在注释中使用类型是不明智的。他们的整个想法是提供一些关于论点应该是什么的线索。为什么 FunctionType 不是一个提示?
  • @MarcelWilson -- 嗯,像Callable[[int, int], str] 这样的类型将比FunctionType 更具描述性和实用性。如前所述,后一种类型具有不必要的限制:它与定义__call__ 方法的类不兼容。在某些情况下,有这种区别很有用,但这些情况很少见。是的,在类型提示中使用类型是你应该做的——但是使用来自 types 模块的特定类型,例如 FunctionType,通常会导致不太精确的签名。
  • 对于只存在于types 但不存在于typing 中的GeneratorType 呢?我希望能够表明正在返回一个生成器,但不能仅使用typing 来执行此操作。还是我错过了什么?
猜你喜欢
  • 2015-02-18
  • 1970-01-01
  • 1970-01-01
  • 2023-03-31
  • 1970-01-01
  • 2021-01-22
  • 2020-06-06
  • 1970-01-01
相关资源
最近更新 更多