Following system colour scheme - Python 增强提案 Selected dark colour scheme - Python 增强提案 Selected light colour scheme - Python 增强提案

Python 增强提案

PEP 312 – 简易隐式 Lambda

作者:
Roman Suzi <rnd at onego.ru>, Alex Martelli <aleaxit at gmail.com>
状态:
推迟
类型:
标准跟踪
创建:
2003 年 2 月 11 日
Python 版本:
2.4
历史记录:


目录

摘要

此 PEP 提案建议在某些情况下,当不产生语法歧义时,可以将无参数 lambda 关键字省略。

推迟

BDFL 讨厌一元冒号语法。此 PEP 需要重新设计,找到更符合 Python 风格的语法(也许可以采用其他一元运算符)。请参阅 2005 年 6 月 17 日的 python-dev 讨论 [1].

此外,最好消除那些毫无机会的替代方案。示例部分很好地突出了可读性改进。如果能添加更多示例以及实际应用的引用(而不是抽象的虚拟调用 :A:B),将更具说服力。

动机

Lambda 用于定义匿名函数,例如用作回调或(伪)延迟求值方案。通常,人们不会在合适的情况下使用 lambda,仅仅因为关键字 “lambda” 使代码看起来很复杂。在某些特殊情况下,可以省略 lambda,只需对语法进行微小且向后兼容的更改,就可以提供一种简单的方法来解决这种 “lambda 恐惧症”。

基本原理

有时人们不使用 lambda 是因为他们害怕引入一个带理论背景的术语。此提案通过省略 “lambda” 关键字本身,简化了引入无参数 lambda 的过程。实现可以通过简单地更改语法来完成,使其在一些众所周知的用例中隐式地推断出 “lambda” 关键字。特别是,添加周围的括号可以让您在任何地方指定空参数 lambda。

语法

在以下情况下,可以省略无参数 “lambda” 关键字

  • 在命名参数赋值或默认值赋值中,紧接在 “=” 后面;
  • 在任何表达式中,紧接在 “(” 后面;
  • 在函数参数列表中,紧接在 “,” 后面;
  • 在字典字面量中,紧接在 “:” 后面;(未实现)
  • 在赋值语句中;(未实现)

使用示例

  1. 内联 if
    def ifelse(cond, true_part, false_part):
        if cond:
            return true_part()
        else:
            return false_part()
    
    # old syntax:
    print ifelse(a < b, lambda:A, lambda:B)
    
    # new syntax:
    print ifelse(a < b, :A, :B)
    
    # parts A and B may require extensive processing, as in:
    print ifelse(a < b, :ext_proc1(A), :ext_proc2(B))
    
  2. 锁定
    def with(alock, acallable):
        alock.acquire()
        try:
            acallable()
        finally:
            alock.release()
    
    with(mylock, :x(y(), 23, z(), 'foo'))
    

实现

实现需要对 Python 源代码中的 Grammar/Grammar 文件进行一些调整,还需要对 Modules/parsermodule.c 进行一些调整,以实现语法和语义上的更改。

(需要一些语法/解析器专家才能完成完整的实现。)

以下是对 Grammar 文件的更改,以允许隐式 lambda

varargslist: (fpdef ['=' imptest] ',')* ('*' NAME [',' '**'
NAME] | '**' NAME) | fpdef ['=' imptest] (',' fpdef ['='
imptest])* [',']

imptest: test | implambdef

atom: '(' [imptestlist] ')' | '[' [listmaker] ']' |
'{' [dictmaker] '}' | '`' testlist1 '`' | NAME | NUMBER | STRING+

implambdef: ':' test

imptestlist: imptest (',' imptest)* [',']

argument: [test '='] imptest

需要三个新的非终结符:imptest 用于可能出现隐式 lambda 的位置,implambdef 用于隐式 lambda 定义本身,imptestlist 用于可能出现 imptest 的位置。

此实现尚未完成。首先,因为 Parser 模块中的某些文件需要更新。其次,一些额外的部分尚未实现,请参阅上面的语法部分。

讨论

此功能并不高调(唯一新颖的部分是 lambda 的缺失)。该功能旨在从语法上使空参数 lambda 更具吸引力,以便在某些简单情况下提供表达式的延迟求值。此提案并非针对更高级的用例(要求 lambda 的参数)。

有一个关于隐式 lambda 的替代方案:具有未用参数的隐式 lambda。在这种情况下,由这种 lambda 定义的函数可以接受任何参数,即等效于:lambda *args: expr。这种形式将更加强大。在标准库中搜索发现这种 lambda 确实在使用。

另一个扩展可以提供一种方法,将参数列表传递给由隐式 lambda 定义的函数。但是,这些参数需要一些特殊的名称才能访问,并且不太可能包含在语言中。这些参数可能的局部名称有:___args____。例如

reduce(:_[0] + _[1], [1,2,3], 0)
reduce(:__[0] + __[1], [1,2,3], 0)
reduce(:__args__[0] + __args__[1], [1,2,3], 0)

这些形式看起来不太美观,在 PEP 作者看来,这些形式不足以证明在这种情况下删除 lambda 关键字。

致谢

在 2003 年 2 月 8 日 16:39:30 -0800 的 comp.lang.python 上,Paul Rubin 首次提出删除 lambda 的想法,当时他正在讨论主题 “供审查:PEP 308 - if-then-else 表达式” [2].

参考文献


来源:https://github.com/python/peps/blob/main/peps/pep-0312.rst

最后修改:2023-09-09 17:39:29 GMT