Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/347.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么Python赋值不返回值?_Python_Python 3.x_Language Design - Fatal编程技术网

为什么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将被视为关键字

为什么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
将被视为关键字参数。但是另一对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:…

我确实同意有时我希望它能起作用,但我也错过了一块代码,这肯定不会改变

  • Python的语法比C的语法要简单得多
  • 它的作用域规则比C复杂得多
  • 在每个表达式中使用括号会降低代码的可读性,python避免了这一点
  • 如果assigments是表达式,则必须重新处理这些和许多其他特性。对我来说,这就像是一个交易,你必须作出这样的可读代码和有用的功能。 为了拥有

    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洛特:我想我在想一些简单的例子(比如