编程语言
首页 > 编程语言> > 为什么Python的`lambda`表达式中不允许赋值?

为什么Python的`lambda`表达式中不允许赋值?

作者:互联网

这不是Assignment inside lambda expression in Python的重复,也就是说,我不会问如何欺骗Python在lambda表达式中赋值.

我有一些λ演算背景.考虑以下代码,它
看起来Python非常愿意在lambda中执行副作用
表情:

#!/usr/bin/python

def applyTo42(f):
    return f(42)

def double(x):
    return x * 2

class ContainsVal:
    def __init__(self, v):
        self.v = v

    def store(self, v):
        self.v = v

def main():

    print('== functional, no side effects')

    print('-- print the double of 42')
    print(applyTo42(double))

    print('-- print 1000 more than 42')
    print(applyTo42(lambda x: x + 1000))

    print('-- print c\'s value instead of 42')
    c = ContainsVal(23)
    print(applyTo42(lambda x: c.v))


    print('== not functional, side effects')

    print('-- perform IO on 42')
    applyTo42(lambda x: print(x))

    print('-- set c\'s value to 42')
    print(c.v)
    applyTo42(lambda x: c.store(x))
    print(c.v)

    #print('== illegal, but why?')
    #print(applyTo42(lambda x: c.v = 99))

if __name__ == '__main__':
    main()

但如果我取消注释线

    print('== illegal, but why?')
    print(applyTo42(lambda x: c.v = 99))

我去拿

SyntaxError: lambda cannot contain assignment

为什么不?这背后的深层原因是什么?

>正如代码所示,它不能是关于“纯度”的
功能感.
>我能想象的唯一解释是,assignemts没有
什么都没有,甚至没有.但这听起来很蹩脚而且会
很容易修复(一种方法:使lambda表达式返回None,如果
身体是一个声明).

不是答案:

>因为它是这样定义的(我想知道它为什么这样定义).
>因为它在语法中(见上文).
>如果你需要陈述,请使用def(我没有询问如何获得
声明成功能).

“这会改变语法/语言/语义”如果你能想出一个这样的变化的例子,以及它为什么会变坏,那么它就可以作为答案.

解决方法:

lambda存在的全部原因是它是一个表达式.1如果你想要像lambda这样的东西但是是一个声明,那就是def.

Python表达式不能包含语句.事实上,这是该语言的基础,而Python从这个决定中获得了很多好处.这就是流量控制缩进的原因,而不是像许多其他尝试(如CoffeeScript)那样笨重.这是你可以通过略读每一行中的第一个对象来读取状态变化的原因.对于编译器和人类读者来说,这甚至是语言易于解析的部分原因

改变Python有一些方法可以“逃避”语句 – 表达式的差异,除非是以非常谨慎和有限的方式,将它变成一种完全不同的语言,并且不再具有导致人们选择的许多好处的语言Python首先.

改变Python以生成大多数语句表达式(比如说,Ruby)会再次将它变成一种完全不同的语言,而没有Python当前的好处.

如果Python确实做了其中任何一个更改,那么首先不再有lambda的原因; 2,3你可以在表达式中使用def语句.

如何更改Python而不是制作赋值表达式?好吧,很明显会破坏“你可以通过略读每一行中的第一个对象来读取状态变化”.虽然Guido通常关注的事实是,如果垃圾邮件=鸡蛋是一个错误,往往是一个有用的东西.

事实上Python确实为你提供了在需要时解决这个问题的方法,比如setattr甚至在globals()上显式调用__setitem__,这并不意味着它应该具有直接的语法支持.很少需要的东西不值得语法糖 – 对于那些不寻常的东西,它应该在实际完成时引起眉毛和/或红旗更是如此.

1.当他最初在Python 1.0中添加lambda时,我不知道这是否是Guido的理解.但这绝对是在Python 3.0中没有删除lambda的原因.

2.实际上,Guido多次提出允许人类可以在头脑中运行的LL(1)解析器是语言基于语句的充分理由,甚至不需要其他好处.讨论. I wrote about this a few years ago,如果有人有兴趣.

3.如果你想知道为什么这么多语言确实有一个lambda表达式尽管已经有了def:在许多语言中,从C到Ruby,函数不是可以传递的第一类对象,所以他们必须发明第二件事是一流的,但就像一个功能.在其他方面,从Smalltalk到Java,功能甚至不存在,只有方法,所以再次,他们不得不发明第二个不是方法而是像一个方法一样的东西. Python没有这些问题.

4.一些语言,如C#和JavaScript,实际上具有完美的内联函数定义,但添加了某种lambda语法作为纯语法糖,使其更简洁,更少样板.这实际上可能值得在Python中进行(尽管到目前为止,每次尝试使用良好的语法都会失败),但它不会是当前的lambda语法,它几乎和def一样冗长.

标签:side-effects,python,lambda,python-internals
来源: https://codeday.me/bug/20191007/1868933.html