为什么Python的`lambda`表达式中不允许赋值? [英] Why are assignments not allowed in Python's `lambda` expressions?

查看:103
本文介绍了为什么Python的`lambda`表达式中不允许赋值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这不是 Python中的lambda表达式内的赋值的重复项,即,我不是询问如何诱使Python分配lambda表达式.

This is not a duplicate of Assignment inside lambda expression in Python, i.e., I'm not asking how to trick Python into assigning in a lambda expression.

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

I have some λ-calculus background. Considering the following code, it looks like Python is quite willing to perform side-effects in lambda expressions:

#!/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()

但是如果我取消注释的话

But if I uncomment the lines

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

我会得到

SyntaxError: lambda cannot contain assignment

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

  • 如代码所示,它不能与纯度"有关. 功能感.

  • As the code demonstrates, it cannot be about "purity" in a functional sense.

我能想象的唯一解释是赋值器不会 返回任何内容,甚至不返回None.但这听起来la脚,而且会 易于修复(一种方法:如果满足以下条件,则使lambda表达式返回None body是一个语句).

The only explanation I can imagine is that assignemts do not return anything, not even None. But that sounds lame and would be easy to fix (one way: make lambda expressions return None if body is a statement).

没有答案:

  • 因为它是用这种方式定义的(我想知道为什么这样定义).

  • Because it's defined that way (I want to know why it's defined that way).

因为它在语法中(请参见上文).

Because it's in the grammar (see above).

如果需要声明,请使用def(我没有询问如何获取 语句转换为函数).

Use def if you need statements (I did not ask for how to get statements into a function).

如果您能提出这样的更改的示例以及它为什么不好的话,这将改变语法/语言/语义"可以作为答案.

"This would change syntax / the language / semantics" would be ok as an answer if you can come up with an example of such a change, and why it would be bad.

推荐答案

lambda存在的全部原因是它是一个表达式. 1 如果您想要类似lambda但又是一个声明,只是def.

The entire reason lambda exists is that it's an expression.1 If you want something that's like lambda but is a statement, that's just def.

Python表达式不能包含语句.实际上,这是该语言的基础,Python做出了很多决定.这是缩进进行流控制的原因,而不是像其他许多尝试(例如CoffeeScript)那样笨拙.这就是您可以通过略读每行中的第一个对象来读取状态更改的原因.无论是对于编译器还是对人类读者来说,这都是该语言易于解析的部分原因. 2

Python expressions cannot contain statements. This is, in fact, fundamental to the language, and Python gets a lot of mileage out of that decision. It's the reason indentation for flow control works instead of being clunky as in many other attempts (like CoffeeScript). It's the reason you can read off the state changes by skimming the first object in each line. It's even part of the reason the language is easy to parse, both for the compiler and for human readers.2

改变Python以某种方式逃避"语句-表达式的鸿沟,除非以一种非常谨慎和有限的方式,否则它将变成一种完全不同的语言,并且不再具有导致这种优势的许多优点.人们首先选择Python.

Changing Python to have some way to "escape" the statement-expression divide, except maybe in a very careful and limited way, would turn it into a completely different language, and one that no longer had many of the benefits that cause people to choose Python in the first place.

更改Python来制作大多数语句表达式(例如Ruby)会使它再次变成完全不同的语言,而没有Python的当前好处.

Changing Python to make most statements expressions (like, say, Ruby) would again turn it into a completely different language without Python's current benefits.

如果Python did 进行了其中的任何更改,那么首先就不再需要lambda的原因; 2,3 只需在表达式内使用def语句即可.

And if Python did make either of those changes, then there'd no longer be a reason for lambda in the first place;2,3 you could just use def statements inside an expression.

如何将Python改为代做赋值表达式呢?好吧,很明显,这将打破您可以通过浏览每行中的第一个对象来读取状态更改".尽管Guido通常将重点放在if spam=eggs是错误而不是有用的事实上.

What about changing Python to instead make assignments expressions? Well, it should be obvious that would break "you can read off the state changes by skimming the first object in each line". Although Guido usually focuses on the fact that if spam=eggs is an error more often than a useful thing.

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

The fact that Python does give you ways to get around that when needed, like setattr or even explicitly calling __setitem__ on globals(), doesn't mean it's something that should have direct syntactic support. Something that's very rarely needed doesn't deserve syntactic sugar—and even more so for something that's unusual enough that it should raise eyebrows and/or red flags when it actually is done.

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

1. I have no idea whether that was Guido's understanding when he originally added lambda back in Python 1.0. But it's definitely the reason lambda wasn't removed in Python 3.0.

2.实际上,Guido多次建议,允许人脑中运行的LL(1)解析器是该语言基于语句的充分理由,以至于甚至不需要讨论其他好处. . 几年前,我写过这篇文章,如果有人感兴趣的话. /sub>

2. In fact, Guido has, multiple times, suggested that allowing an LL(1) parser that humans can run in their heads is sufficient reason for the language being statement-based, to the point that other benefits don't even need to be discussed. I wrote about this a few years ago if anyone's interested.

3.如果您想知道为什么这么多的语言 do 尽管已经具有def却具有lambda表达式:在从C ++到Ruby的许多语言中,函数不是可以被传递出去,所以他们不得不发明第二类,它是一流的,但是像函数一样工作.在另一些情况下,从Smalltalk到Java,函数甚至都不存在,仅存在方法,因此,他们不得不发明第二件事,它不是方法,而是像方法一样工作. Python都没有这些问题.

3. If you're wondering why so many languages do have a lambda expression despite already having def: In many languages, ranging from C++ to Ruby, function aren't first-class objects that can be passed around, so they had to invent a second thing that is first-class but works like a function. In others, from Smalltalk to Java, functions don't even exist, only methods, so again, they had to invent a second thing that's not a method but works like one. Python has neither of those problems.

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

4. A few languages, like C# and JavaScript, actually had perfectly working inline function definitions, but added some kind of lambda syntax as pure syntactic sugar, to make it more concise and less boilerplatey. That might actually be worth doing in Python (although every attempt at a good syntax so far has fallen flat), but it wouldn't be the current lambda syntax, which is nearly as verbose as def.

这篇关于为什么Python的`lambda`表达式中不允许赋值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆