为什么我不能在类型提示中使用`function`,就像我可以使用`int`、`str`和`list`一样?

15 浏览
0 Comments

为什么我不能在类型提示中使用`function`,就像我可以使用`int`、`str`和`list`一样?

我如何将变量的类型提示指定为函数类型?没有 typing.Function,且在相关的 PEP PEP 483 中也找不到相关信息。

0
0 Comments

为什么我不能像使用`int`、`str`和`list`一样在类型提示中使用`function`?这个问题的出现原因是由于类型提示中没有直接支持`function`这个类型。然而,可以通过使用`typing.Callable`来解决这个问题。`typing.Callable`表示一个可调用的对象,可以作为函数的参数类型进行注解。

例如,我们可以这样使用`typing.Callable`:

from typing import Callable
def my_function(func: Callable):
    # 函数体

需要注意的是,`Callable`本身等价于`Callable[..., Any]`。`Callable[..., Any]`表示接受任意数量和类型的参数,并返回任意类型的值。如果这样的约束太过宽松,我们也可以指定参数列表和返回类型的具体类型。

例如,假设有如下函数:

def sum(a: int, b: int) -> int:
    return a + b

对应的类型注解为:

Callable[[int, int], int]

其中,参数类型在外层方括号中进行子脚本标记,返回类型作为外层方括号的第二个元素。一般形式为:

Callable[[ParamType1, ParamType2, ..., ParamTypeN], ReturnType]

关于`*args`、`**kwargs`、仅关键字参数和仅位置参数的调用约定,官方文档中并没有明确说明。不过,我们可以根据需要自行使用`Callable`进行类型注解。

需要注意的是,`typing.Callable`和`collections.abc.Callable`并不完全相同。`typing.Callable`更加常用且推荐使用。然而,`collections.abc.Callable`提供了一些函数特有的属性,可以用于对函数进行更细粒度的类型注解。

对于类方法而言,由于所有方法都需要以`self`作为参数,因此对于方法的类型注解是否有所不同,官方文档并未给出明确答案。

总结一下,虽然类型提示中无法直接使用`function`类型,但可以通过使用`typing.Callable`来实现对函数类型的注解。使用`Callable`可以指定参数列表和返回类型的具体类型。需要注意的是,`typing.Callable`和`collections.abc.Callable`有些差异,建议使用`typing.Callable`进行类型注解。

0
0 Comments

为什么在类型提示中不能使用`function`,就像可以使用`int`、`str`和`list`一样?

这个问题的出现原因是为了在PyCharm中实现丰富的代码补全功能。使用`Callable`并没有导致PyCharm建议该对象具有`.__code__`属性,而这正是我想要的。

我偶然发现了`types`模块,并且使用`from types import FunctionType`可以使用`FunctionType`注释一个对象,然后,PyCharm现在建议我的对象具有`.__code__`属性。

问题提问者没有明确说明为什么这个类型提示对他们有用。`Callable`对于任何实现了`.__call__()`方法的对象都有效,但为了进一步明确接口,我提出了使用`types`模块。

遗憾的是,Python需要两个非常相似的模块。

相反,Visual Studio Code中的Pylance只接受`Callable`而不接受`FunctionType`作为有效的类型提示。

0
0 Comments

为什么我不能在类型提示中使用`function`,就像我可以使用`int`、`str`和`list`一样?

在Python中,类型提示(type hints)是一种静态类型检查的工具,它可以帮助开发者在代码编写阶段就发现潜在的类型错误。类型提示可以用于函数参数、返回值以及变量声明等地方。

然而,尽管我们可以在类型提示中使用`int`、`str`和`list`等内置类型,却无法直接使用`function`类型。为什么呢?

原因是类型提示在设计上是懒惰求值(lazy evaluated)的。这意味着类型提示中的表达式不会被立即求值,而是在需要时才进行求值。这种设计可以提高性能和灵活性,但也导致了一些限制。

例如,在上述代码中,我们尝试使用`type(abs)`作为函数参数的类型提示。`abs`是一个内置函数,我们希望传入的函数参数也是类似的内置函数。然而,当我们运行类型检查工具`mypy`时,会得到一个错误:`Invalid type comment or annotation`。这是因为`mypy`无法解析`type(abs)`这样的表达式。

那么,有没有解决办法呢?

解决办法是使用`type[...]`而不是`type(...)`。例如,我们可以将上述代码改写为:

def f(my_function: type[abs]) -> int:
    return my_function(100)

通过使用`type[abs]`,我们告诉类型检查工具`mypy`,函数参数的类型应该是`abs`这个内置函数。

需要注意的是,`type[abs]`实际上是`builtin_function_or_method`类型。这可能不被很多工具所理解,因为它没有指定参数,并且在这种情况下甚至是不正确的。

尽管我们不能直接在类型提示中使用`function`类型,但我们可以通过使用`type[...]`来指定特定的函数类型。这样,我们可以更精确地描述函数参数的类型,提高代码的可读性和可维护性。

0