ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

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

2019-10-07 20:57:29  阅读:499  来源: 互联网

标签:side-effects python lambda python-internals


这不是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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有