为什么Python赋值语句而不是表达式?如果它是一个表达式,它返回赋值中右侧的值,那么在某些情况下它会允许更简洁的代码。有什么问题我看不到吗?
例如:
# lst is some sequence
# X is come class
x = X()
lst.append(x)
本可以改写为:
lst.append(x = X())
嗯,确切地说,上述情况不起作用,因为x
将被视为关键字参数。但另一对parens(或关键字参数的另一个符号)可以解决这个问题。
答案 0 :(得分:39)
有许多人认为赋值是表达式,尤其是像Python这样的语言,其中任何值在条件中是允许的(不仅仅是某些布尔类型的值),容易出错。据推测,Guido是那些有这种感觉的人。经典错误是:
if x = y: # oops! meant to say ==
Python中的情况也比C语言更复杂,因为在Python中,对变量的第一个赋值也是它的声明。例如:
def f():
print x
def g():
x = h()
print x
在这两个函数中,“print x
”行执行不同的操作:一个引用全局变量x
,另一个引用局部变量x
。由于分配,x
中的g
是本地的。{1}}。如果可以将赋值放在一些更大的表达式/语句中,这可能会更加令人困惑(比现在已经多了)。
答案 1 :(得分:14)
现实世界的答案:不需要它。
您在C中看到的大多数情况都是因为错误处理是手动完成的:
if((fd = open("file", O_RDONLY)) == -1)
{
// error handling
}
类似于编写许多循环的方式:
while(i++ < 10)
;
这些常见情况在Python中有所不同。错误处理通常使用异常处理;循环通常使用迭代器。
反对它的论点不一定是惊天动地的,但它们与在Python中它并不那么重要的事实相称。
答案 2 :(得分:7)
我认为这是为了防止某些经典错误而故意在Guido身上。 E.g。
if x = 3: print x
当你真正想说的时候
if x == 3: ...
我同意有时候我希望它会起作用,但我也会错过{
和}
围绕一段代码,而且肯定不会改变。
答案 3 :(得分:7)
您可以期望在不久的将来的python版本中实现对(x := y)
表达式的支持。 Guido最近于2018年7月接受了一项建议PEP 572,以支持python中的赋值表达式。 (也有较早的提议,例如撤消PEP 379。)
回想一下,在版本3之前,print
还是一个语句,而不是一个表达式。
注意:语句x = y = z
为多个目标(或多个 target-list ,因为也允许拆包)分配了相同的值早已在python中得到支持,但已实现为特殊的syntax,而不是通过链接连续的赋值子表达式来实现。 (实际上,执行各个分配的顺序是相反的。)
答案 4 :(得分:4)
如果分配是表达式,则必须重新制作这些和许多其他功能。对我而言,这就像是为了拥有可读代码和有用功能而必须达成的协议。
if a and (h not in b): ...
而不是
if (a && !(h in b)) { ... }
[不是在谈论经典(如果a = b :)那种错误。]
答案 5 :(得分:-1)
进入品味讨论,或任何被认为是这样的讨论,无论论证多么好,都是浪费时间。
在更一般的原则之外,我赋予表达式的首选实际原因是当我想要将字符串与多个模式(提取子模式)匹配时,具有可读的case语句等效,直到成功为止。也许有人有一个很好的解决方案,我没有看到。
无论如何......为什么不通过模块文件开头的可解释注释使两个世界变得快乐,这些注释明确指出如果程序员需要,赋值可以用作表达式?
对当前情况感到满意的人不会看到任何变化,并且仍会以相同的方式检测到他们的语法错误。
那些想要将作业用作表达的人只需说出来。
我没有看到允许在不使用它的现有程序中使用赋值作为表达式(通过简单地添加上面建议的注释)将改变该程序的语义。
和平。
post-sriptum - 这是在下面讨论的第1部分的前五个段落发布后添加的。
我不知道为什么Python设计师会做出这样的选择。避免
诚然,常见错误if a=b : ...
而不是if a==b : ...
几乎没有理由。
首先,用另一种表示法可以很容易地避免它
分配,例如:=
或<-
,更适合自分配
不是对称的,并且在Python的早期祖先中使用过。
其次,在另一个背景下容忍同样的问题。一罐
写a = b=c
,而实际上是写a = b==c
很不一样。 b
和c
时错误不明显
是大表达。而且,虽然它可能会
如果语言是静态类型的,则检测为类型错误
在Python这样的动态类型语言中并非如此(这是
在所有情境中=
与==
实际相同。)
这种宽容更令人惊讶的是多重赋值
a = b = c
形式几乎不是语言的基本特征,
这不是一个非常有用的功能。
这看起来像是早期设计决策的残余,有些是有动力的 与C或Bash等现有语言的相似之处,因为Python 也是一种脚本语言,但已经远不止于此。在 换句话说,它似乎比经过深思熟虑的设计更偶然。 希望这不是人们在谈论时的想法 pythonicity。
这就是说,这些都是轻微的句法限制,无论多么烦人。 这种语言似乎整体设计得更好(有一些心理限制 关于范围规则,直到我决定其逻辑)。
这个讨论的一个有趣的方面是禁止 作为表达式的赋值(虽然它可以通过符号来解决) 由于缺少静态类型,也需要改变)。 但是可以预料到没有静态打字,这是一个 合法的设计选择,使得很多bug难以捕获。这是 非常一般的观察。尽管如此,这是由...做出的选择 Python设计师。就这样吧。
然而,他们几乎不会后悔平等和平等之间的混淆 任务将更难捕捉。这只是直接后果, 他们的设计选择的更多灵活性的许多后果之一 错误检测的代价。因此错误检测是一个糟糕的借口 对于这项转让限制。关于表达式赋值将混合功能的事实 和命令式的风格,这是一个非问题。混合已经存在 语言无处不在。
Python是否有书面的理由来记录一般的设计选择,特别是这里讨论的问题?