问题 Python:赋值中的异常


如果我尝试以下代码(在Python 3.2.2中),

def f():
    raise Exception

x = f()

然后它似乎 x 没有被触及 - 要么保持未定义,要么保留以前的任何价值。只要赋值的右侧抛出异常,这种行为是否得到保证?我意识到这是一个非常基本的问题,但是我找不到很多关于分配工作原理的信息。更一般地说,在与任务相关的任何事情发生之前,是否总是评估整个右侧?这在使用时是否正确 setattr,分配给列表的元素,或使用元组解包(即类似的东西) x, y = y, f())?


1033
2017-12-13 16:59


起源

据我所知,这是一致的(只是在PyPy上测试过,它在那里也一样),但我没有看到任何明确的声明,它必须是这种情况。 - Thomas K
好吧,缺乏正式的规范使得这有点困难(C,C ++,Java,JavaScript等人可以引用正式的规范)。但实际上,没有任何实现偏离,并且行为非常重要,以致偏离的实现会被称为破坏。


答案:


Python语言参考指定了:

http://docs.python.org/reference/expressions.html#evaluation-order

Python从左到右评估表达式。请注意,在评估分配时,右侧在左侧之前进行评估。

评估右侧,然后是左侧,然后分配本身发生。从而,

def x():
    print "x"
    fail()

def y():
    print "y"
    fail()

x().a = y()

保证打印“y”并使用NameError失败;它永远不会提出“x”,或尝试任何转让。


13
2017-12-13 17:59





有关的Python文档 转让声明 没有明确说明当右侧提出异常时,永远不会触及赋值的左侧,但在阅读本文之后,似乎证明避免赋值的唯一方法是引发异常。

结论:如果引发异常,则永远不会触及赋值的左侧


0
2017-12-13 18:27