在python三元条件的两侧使用语句

时间:2013-01-23 07:04:27

标签: python syntax ternary

为什么禁止在python的三元条件的任何一方使用语句?我看不出任何明显的原因,以下几个天真的语法示例可能是模糊或破坏的 - 但我确信必须有一个很好的理由为什么它被禁止!

>>> x, y = 0, 0
>>> (x += 1) if random.choice([0, 1]) else (y += 1)
        ^
SyntaxError: invalid syntax

>>> (x if random.choice([0, 1]) else y) += 1
SyntaxError: can't assign to conditional expression


>>> print 'hello world' if random.choice([0, 1]) else raise StandardError()
  File "<stdin>", line 1
    print 'hello world' if random.choice([0, 1]) else raise StandardError()
                                                          ^
SyntaxError: invalid syntax

您能举例说明允许在三元组中使用语句可能是危险的还是定义不明确的?

4 个答案:

答案 0 :(得分:7)

表达式为eval,语句为exec。这是完全不同的东西。

Python开发人员决定严格区分表达式和语句。这将使您“提前失败”,而不是以难以调试的错误结束。

在其他语言中,如C(++),您可以执行

之类的操作
if (i=15) {...}

但你也可以

if (i==15) {...}

在第一个示例中,您为变量i分配了15,然后i评估了if的新值。

更糟糕的是增量/减量运算符。有什么区别

if (i--) {...}

if (--i) {...}

对于第一个示例,评估i的值,然后递增。对于第二个示例,顺序是另一种方式,因此如果之前i1,则结果会有所不同。

在Python中,由于在其他语言中使用这些概念收集的经验,语法禁止这样的事情。

我不太确定这是否完全回答了你的问题,但我希望我至少可以对pythonic方法有所了解。

答案 1 :(得分:4)

这与条件表达式 1 无关。 Python程序由语句组成。大多数语句的大多数部分都是表达式表达式只包含其他表达式。

y += 1是一个语句,不允许在表达式所在的位置。三元条件作为一个整体是一个表达式,它的三个部分中的每一个都是表达式。没有理由允许(x += 1) if random.choice([0, 1]) else (y += 1)而不允许以下任何怪物:

x = (y += 1)
def foo(x=(x += 1)):
    print x
print [x += 1, x *= 10]

表达式是可以被评估为某种值的东西;语句是没有价值的东西。如果允许语句作为条件表达式的“when true”或“when false”操作数,那么为什么不允许任何表达式中的任何语句?毕竟,它会使语法复杂化为特殊情况,因此条件表达式是唯一可以包含语句的表达式。

x = y + pass
[return True, import sys]

这些都没有任何意义。 (x += 1) if random.choice([0, 1]) else (y += 1)也没有,因为条件表达式的整个要点是表达式。因此,它会更真实地出现在声明中,例如:

z = (x += 1) if random.choice([0, 1]) else (y += 1)

您可以设想,x += 1的“值”是x的值(在添加1之前或之后),就像C一样。但它使语言变得更加复杂。而这仍然无法解决以下问题:

z = pass if (import sys) else (while False: print 17)

pass的价值是多少? import sys的?一段时间的循环?

为了完成这项工作,你必须将“语句”作为Python语法中存在的一类东西分离成“表达式语句”和“正常语句”,或者发明一些关于某些值的任意规则各种陈述是。可能两者都有。

简单的事实是,如果你想把它写成一个单一的陈述:

(x += 1) if random.choice([0, 1]) else (y += 1)

然后Python已经有了表达这个想法的语法,就是这样:

if random.choice([0, 1]):
    x += 1
else:
    y += 1

没有必要将语句作为表达式组件的语言(以及可读性)引入复杂性,这样您就可以通过将if语句写为条件表达式(其值被忽略)来混淆+语句。 / p>


1 如果必须的话,称之为“三元条件”,但“三元”或“三元运算符”只是简单的愚蠢。它有3个操作数并不是最重要的事情;这就像调用{{1}}“二元运算符”。

答案 2 :(得分:1)

第一种语法

您的第一个语法实际上是传统的if statement,您尝试在条件和第一个操作相反的情况下写入一行。以这种方式使用单行结构是过分的,而且它很丑陋且难以理解。 Python不是C。

第二种语法

你的第二种语法不起作用,因为Python的条件表达式结果是rvalue,而不是lvalue(该链接谈论的是C和Microsoft,但它只是一个常见术语,发生在每种语言中) 。 rvalue是一个表达式,可能仅出现在赋值的右侧。但是,lvalue可能出现在右侧或左侧。当lvalue位于右侧时,它的仅用于评估左侧的任何内容。当lvalue位于左侧时,地址用于存储评估后的右侧表达式值。

在Python中,所有内容都是引用,lvalue允许更改引用指向的内容,但rvalue不会。

示例:

a = 5 # here a is lvalue
b = a + 1 # here a is rvalue and b is lvalue

rvalue的另一个例子 - 只有表达式是常量。从翻译的角度来看,你的第二次尝试看起来就像

42 = 42 + 1 # WHAT THE HECK!?

为什么

至于为什么它决定使条件表达式没有语句(哎呀,看起来我们已经找到了原因!):作为PEP 308状态,条件表达式是最初引入使用而不是容易出错的x and y or z布尔表达式,由于short-circuit评估,它的工作原理相同。

如果Python允许statements像你的条件那样,那么它必须允许,例如,raise。在一行代码中填充大量逻辑被认为是一种糟糕的Python代码风格(正如我上面所说)。

看看这个

result = some_long_name / some_other_name if some_other_name != 0 else raise ZeroDivisionError

它看起来像一个开头的表达式,但它表现得像一个声明,甚至引发异常! :(考虑到Python建议剥离79个字符的行,你甚至不会在多窗口并排视图中看到raise


答案 3 :(得分:-4)

您使用的是什么版本的python? python 2.4 atleast中不支持这种语法。以下在python 3.3上为我工作。在旁注中,删除paranthesis:

import random
x,y=0,0
x += 1 if random.choice([0,1]) else (y +1)