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 需要回到草图阶段,找到一种更 Pythonic 的语法(也许是另一种一元运算符)。请参见 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 进行一些修改以实现句法和语义上的改变。

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

以下是允许隐式 lambda 所需的 Grammar 更改

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 可能出现的位置。

此实现尚未完成。首先,因为解析器模块中的一些文件需要更新。其次,一些额外的地方尚未实现,请参见上方的语法部分。

讨论

此功能并非高可见性功能(唯一新颖的部分是 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,Paul Rubin 在 comp.lang.python 讨论“征求意见:PEP 308 - If-then-else 表达式”线程时,首次提出了放弃 lambda 的想法 [2]

参考资料


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

最后修改: 2025-02-01 08:59:27 GMT