小编典典

是否可以输入提示 lambda 函数?

all

目前,在 Python 中,可以对函数的参数和返回类型进行类型提示,如下所示:

def func(var1: str, var2: str) -> int:
    return var1.index(var2)

这表明该函数接受两个字符串,并返回一个整数。

但是,这种语法与 lambdas 高度混淆,它看起来像:

func = lambda var1, var2: var1.index(var2)

我已经尝试在参数和返回类型上添加类型提示,但我想不出一种不会导致语法错误的方法。

是否可以输入提示 lambda 函数?如果没有,是否有类型提示 lambdas 的计划,或者任何原因(除了明显的语法冲突)为什么不呢?


阅读 78

收藏
2022-08-27

共1个答案

小编典典

您可以在 Python 3.6 及更高版本中使用PEP 526 variable
annotations
。您可以使用泛型lambda注释分配结果的变量:typing.Callable

from typing import Callable

func: Callable[[str, str], int] = lambda var1, var2: var1.index(var2)

这不会将类型提示信息附加到函数对象本身,仅附加到存储对象的命名空间,但这通常是类型提示所需的全部。

但是,您也可以只使用函数语句;a 提供的唯一优点lambda是您可以将简单表达式的函数定义 放在 更大的表达式中。但是上面的 lambda
不是更大表达式的一部分,它只是赋值语句的一部分,将它绑定到一个名称。这正是def func(var1: str, var2: str): return var1.index(var2)声明将实现的目标。

请注意,您也不能单独注释*args**kwargs参数,作为Callable状态的文档:

没有语法来指示可选或关键字参数;此类函数类型很少用作回调类型。

该限制不适用于带有方法的PEP 544
协议__call__
;如果您需要对应该接受哪些参数进行表达定义,请使用它。您需要 Python 3.8 安装typing- extensions项目以进行反向移植:

from typing_extensions import Protocol

class SomeCallableConvention(Protocol):
    def __call__(self, var1: str, var2: str, spam: str = "ham") -> int:
        ...

func: SomeCallableConvention = lambda var1, var2, spam="ham": var1.index(var2) * spam

对于lambda表达式 本身 ,您不能使用任何注释(Python 类型提示所基于的语法)。该语法仅适用于def函数语句。

来自PEP 3107 - 函数注释

lambda 的语法不支持注解。可以通过在参数列表周围使用括号来更改 lambda
的语法以支持注释。但是,决定不进行此更改,因为:

  • 这将是一个不兼容的变化。
  • 无论如何,Lambda都是绝育的。
  • lambda 始终可以更改为函数。

您仍然可以将注释直接附加到对象,该function.__annotations__属性是可写字典:

>>> def func(var1: str, var2: str) -> int:
...     return var1.index(var2)
...
>>> func.__annotations__
{'var1': <class 'str'>, 'return': <class 'int'>, 'var2': <class 'str'>}
>>> lfunc = lambda var1, var2: var1.index(var2)
>>> lfunc.__annotations__
{}
>>> lfunc.__annotations__['var1'] = str
>>> lfunc.__annotations__['var2'] = str
>>> lfunc.__annotations__['return'] = int
>>> lfunc.__annotations__
{'var1': <class 'str'>, 'return': <class 'int'>, 'var2': <class 'str'>}

当然,当您想在类型提示上运行静态分析器时,并不是说像这样的动态注释会对您有所帮助。

2022-08-27