为什么Python赋值不返回值?
为什么Python赋值是语句而不是表达式?如果它是一个返回赋值中右边值的表达式,那么在某些情况下,它将允许更少的冗长代码。有什么我看不到的问题吗 例如:为什么Python赋值不返回值?,python,python-3.x,language-design,Python,Python 3.x,Language Design,为什么Python赋值是语句而不是表达式?如果它是一个返回赋值中右边值的表达式,那么在某些情况下,它将允许更少的冗长代码。有什么我看不到的问题吗 例如: # lst is some sequence # X is come class x = X() lst.append(x) def f(): print x def g(): x = h() print x 可以改写为: lst.append(x = X()) 准确地说,上面的方法不起作用,因为x将被视为关键字
# lst is some sequence
# X is come class
x = X()
lst.append(x)
def f():
print x
def g():
x = h()
print x
可以改写为:
lst.append(x = X())
准确地说,上面的方法不起作用,因为
x
将被视为关键字参数。但是另一对paren(或者关键字参数的另一个符号)可以解决这个问题。很多人认为,将赋值作为表达式,特别是在Python这样的语言中,条件中允许任何值(不仅仅是某些布尔类型的值),很容易出错。想必Guido也是有这种感觉的人之一。典型错误是:
if x = y: # oops! meant to say ==
Python中的情况也比C语言中的情况要复杂一些,因为在Python中,变量的第一个赋值也是它的声明。例如:
# lst is some sequence
# X is come class
x = X()
lst.append(x)
def f():
print x
def g():
x = h()
print x
在这两个函数中,“
print x
”行执行不同的操作:一个是指全局变量x
,另一个是指局部变量x
。由于分配的原因,g
中的x
是本地的。如果有可能将赋值隐藏在某个更大的表达式/语句中,那么这可能会更令人困惑(比现在更令人困惑)。我相信这是Guido为了防止某些经典错误而故意做的。例如
如果x=3:打印x
当你真的想说
如果x==3:…
我确实同意有时我希望它能起作用,但我也错过了一块代码,这肯定不会改变
if a and (h not in b): ...
而不是
if (a && !(h in b)) { ... }
[不要谈论经典(如果a=b:)类错误。]现实世界的答案是:不需要 在C中看到的大多数情况都是因为错误处理是手动完成的:
if((fd = open("file", O_RDONLY)) == -1)
{
// error handling
}
许多循环的编写方式也类似:
while(i++ < 10)
;
while(i++<10)
;
这些常见情况在Python中的处理方式有所不同。错误处理通常使用异常处理;循环通常使用迭代器
反对它的论据不一定是惊天动地的,但它们与事实相权衡,即它在Python中并不那么重要。进入品味讨论,或任何被认为是这样的讨论,通常都是浪费时间,不管这些论据有多好 在更一般的原则之外,我将赋值作为表达式的首选实际原因是,当我想将字符串与多个模式(提取子模式)匹配时,需要有一个可读的case语句等价物,直到其中一个成功。也许有人有一个很好的解决方案,我没有看到 无论如何。。。为什么不在模块文件的开头添加一条可解释的注释,明确说明赋值可以用作表达式(如果程序员愿意的话),让两个世界都可用,让每个人都高兴呢 对当前情况感到满意的人不会看到任何变化,仍然会以同样的方式检测他们的语法错误 而那些想用赋值来表达的人只需要这么说 我不认为允许在未使用赋值的现有程序中使用赋值作为表达式(通过简单地添加上面建议的注释)会改变该程序的语义 和平
后斯里普顿- 这是在下文讨论的第1节前五段发布后添加的 我不知道为什么Python设计师会做出这样的选择。避免 如果a=b:…而不是a==b:…是常见的错误
几乎没有理由
首先,它可以很容易地用另一种符号来避免
赋值,例如:=
或赋值(子)表达式(x:=y)
自Python 3.8(2019年10月发布)以来就受到支持,因此您现在确实可以将示例重写为lst.append(x:=x())
该提案于2018年7月被Guido正式接受。早些时候也有关于转让表述的提议,例如撤回
回想一下,在第3版之前,print
也是一个语句,而不是一个表达式
已支持将相同值分配给多个目标(或者更确切地说,多个目标列表,因为也允许解包)的语句x=y=z
(例如,自版本1起),但该语句是作为特殊语句实现的,而不是通过链接连续的分配子表达式来实现的。实际上,执行单个赋值的顺序是相反的:嵌套海象(x:=(y:=z))
必须在x
之前赋值给y
,而x=y=z
在y
之前赋值给x
(如果您设置/分配给重载的类的下标或属性以产生一些副作用,这可能是相关的)。您的代码示例与此问题有什么关系?@Ignacio:我的错误。编辑的版本(@Laurence Gonsalves)很好。“有什么问题我看不到吗?”似乎“更不详细的代码”不知何故,这不是个问题。简洁、神秘的代码高尔夫似乎是个问题。你是出于某种原因打折了吗?@S洛特:我想我在想一些简单的例子(比如