为什么Python赋值没有返回值?
为什么Python赋值是一个语句而不是一个表达式?如果它是一个返回赋值右侧值的表达式,那么在某些情况下它会允许更简洁的代码。有什么问题我看不到吗?
例如:
# lst is some sequence
# X is come class
x = X()
lst.append(x)
可以重写为:
lst.append(x = X())
嗯,准确地说,上面的代码不起作用,因为 x
将被视为关键字参数。但另一对括号(或关键字参数的另一个符号)可以解决这个问题。
Why is Python assignment a statement rather than an expression? If it was an expression which returns the value of the right hand side in the assignment, it would have allowed for much less verbose code in some cases. Are there any issues I can't see?
For example:
# lst is some sequence
# X is come class
x = X()
lst.append(x)
could have been rewritten as:
lst.append(x = X())
Well, to be precise, the above won't work because x
would be treated as a keyword argument. But another pair of parens (or another symbol for keyword arguments) would have resolved that.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
许多人认为用表达式进行赋值很容易出错,尤其是在像 Python 这样的语言中,其中条件中允许任何值(不仅仅是某些布尔类型的值)。想必吉多就是有这种感觉的人之一。典型的错误是:
Python 中的情况比 C 等语言中的情况要复杂一些,因为在 Python 中,对变量的第一次赋值也是它的声明。例如:
在这两个函数中,“
print x
”行执行不同的操作:一个引用全局变量x
,另一个引用局部变量x。由于赋值,
g
中的x
是本地的。如果可以将赋值埋入一些更大的表达式/语句中,这可能会更加令人困惑(比现在更混乱)。There are many who feel that having assignments be expressions, especially in languages like Python where any value is allowable in a condition (not just values of some boolean type), is error-prone. Presumably Guido is/was among those who feel that way. The classic error is:
The situation is also a bit more complicated in Python than it is in a language like C, since in Python the first assignment to a variable is also its declaration. For example:
In these two functions the "
print x
" lines do different things: one refers to the global variablex
, and the other refers to the local variablex
. Thex
ing
is local because of the assignment. This could be even more confusing (than it already is) if it was possible to bury the assignment inside some larger expression/statement.自 Python 3.8(2019 年 10 月发布)起支持赋值(子)表达式
(x := y)
,因此您现在确实可以将示例重写为lst.append(x := X())
。该提案 PEP 572 于 2018 年 7 月被 Guido 正式接受。也有早期关于赋值表达式的提案,例如已撤回的 PEP 379。
回想一下,在版本 3 之前,
print
也是一个语句而不是一个表达式。已经支持将相同值分配给多个目标(或者更确切地说,多个目标列表,因为也允许解包)的语句 x = y = z(例如,因为版本 1),但作为特殊的 语法 实现,而不是通过链接连续的赋值子表达式。事实上,执行各个赋值的顺序是相反的:嵌套海象
(x := (y := z))
必须在x 之前赋值给
,而y
x = y = z
在y
之前分配给x
(如果您设置/分配给下标,这可能是相关的)或已重载以产生某些副作用的类的属性)。Assignment (sub-)expressions
(x := y)
are supported since Python 3.8 (released Oct. 2019), so you can indeed now rewrite your example aslst.append(x := X())
.The proposal, PEP 572, was formally accepted by Guido in July 2018. There had also been earlier proposals for assignment expressions, such as the withdrawn PEP 379.
Recall that until version 3,
print
was also a statement rather than an expression.The statement
x = y = z
to assign the same value to multiple targets (or rather, multiple target-lists, since unpacking is also permitted) was already supported (e.g. since version 1) but is implemented as a special syntax rather than by chaining successive assignment sub-expressions. Indeed, the order in which the individual assignments are performed is reversed: nested walruses(x := (y := z))
must assign toy
beforex
, whereasx = y = z
assigns tox
beforey
(which may be pertinent if you set/assign to the subscripts or attributes of a class that has been overloaded to create some side-effect).现实世界的答案是:不需要。
您在 C 中看到的大多数情况都是因为错误处理是手动完成的:
对于许多循环的编写方式也是如此:
这些常见情况在 Python 中的处理方式有所不同。错误处理通常使用异常处理;循环通常使用迭代器。
反对它的论点不一定是惊天动地的,但它们与它在 Python 中并不那么重要这一事实相权衡。
The real-world answer: it's not needed.
Most of the cases you see this in C are because of the fact that error handling is done manually:
Similarly for the way many loops are written:
These common cases are done differently in Python. Error handling typically uses exception handling; loops typically use iterators.
The arguments against it aren't necessarily earth-shattering, but they're weighed against the fact that it simply isn't that important in Python.
我相信 Guido 是故意这样做的,目的是为了防止某些经典错误。例如,
当你实际上想说
我确实同意时,有时我希望它能起作用,但我也错过了围绕代码块的
{
和}
,这肯定是不会改变。I believe this was deliberate on Guido's part in order to prevent certain classic errors. E.g.
when you actually meant to say
I do agree there are times I wished it would work, but I also miss
{
and}
around a block of code, and that sure isn't going to change.如果分配是表达式,则必须重新设计这些功能和许多其他功能。对我来说,这就像你必须达成一笔交易才能拥有如此可读的代码和有用的功能。
为了避免出现
[
不谈论经典的(如果 a = b:) 类型的错误。]
If assigments were expressions, these and many other features would have to be re-worked. For me it is like a deal you have to make in order to have such readable code and useful features.
In order to have
rather than
[not talking about the classic (if a = b:) kind of error.]