Python文档中的条件表达式

时间:2018-01-17 15:50:13

标签: python python-3.x

如果我理解正确,在Python3中,条件表达式的形式是" x如果C else y"。例如,如果我理解正确,下面的块是一个条件表达式,它返回字符串' a'

'a' if 0<1 else 'b'

而以下块是一个返回&#39; b&#39;

的条件表达式
'a' if 0>1 else 'b'

在Python语言参考中,grammar rule for conditional expressions由这些行给出:

conditional_expression ::=  or_test ["if" or_test "else" expression]   

我不理解这条规则,因为例如我会在上面的例子中说'a'0>1来自or_test'b'是派生自expression,而对我来说'a''b'都应该通过相同的规则派生(expr此处)。对我来说唯一有意义的就是用

替换第一个语法规则
conditional_expression ::=  expression \["if" or_test "else" expression\]

我在这里缺少什么?

1 个答案:

答案 0 :(得分:1)

简而言之:因为它会引入歧义。

  

我不明白这个规则,因为例如我会在上面的例子中说'a'0>1来自or_test'b'来自表达式,而对我而言,'a''b'都应该使用相同的规则(expr此处)来推导。

or_testexpr都可以生成字符串文字。事实上,如果我们向下移动语法,我们会看到:

or_test  ::=  and_test | or_test "or" and_test
and_test ::=  not_test | and_test "and" not_test
not_test ::=  comparison | "not" not_test
comparison    ::=  or_expr ( comp_operator or_expr )*
or_expr  ::=  xor_expr | or_expr "|" xor_expr
xor_expr ::=  and_expr | xor_expr "^" and_expr
and_expr ::=  shift_expr | and_expr "&" shift_expr
shift_expr ::=  a_expr | shift_expr ( ">" ) a_expr
a_expr ::=  m_expr | a_expr "+" m_expr | a_expr "-" m_expr
m_expr ::=  u_expr | m_expr "*" u_expr | m_expr "//" u_expr | m_expr "/" u_expr
            | m_expr "%" u_expr
u_expr ::=  power | "-" u_expr | "+" u_expr | "~" u_expr
power ::=  primary ["**" u_expr]
primary ::=  atom | attributeref | subscription | slicing | call
atom      ::=  identifier | literal | enclosure
literal ::=  stringliteral | bytesliteral
             | integer | floatnumber | imagnumber

因此最终or_test可以导致字符串文字。您可以看到or_test作为表达式,但在某些情况下不再可能(除非我们使用括号)。

我们无法对or_test执行的两件重要事情是再次构建if - then - else;并构造一个lambda表达式。是的,我们可以将第一个项目设为lambda表达式,将新if - then设置为else,但不能不使用括号。

为什么我们这有必要?一个语法应该是毫不含糊的。这意味着如果我们从某个表达式构造语法树,那么应该只有一个这样的树。

如果我们允许使用expression作为第一项,我们可以编写如下表达式:

'a' if a else 'b' if c else 'c'

现在我们可以在Python中编写它,因为Python可以推导出'a'属于or_testa属于第二个or_test'b' if c else 'c'expression。如果前者是表达式,我们也可以将'a' if a else 'b'与表达式匹配(根据 Python 标准,这是错误的。)

使用lambda表达式也是如此。如果我们写:

lambda a, b: 'a' if a else 'b' if c else 'c'

然后Python会将其解析为:

lambda a, b: ('a' if a else 'b' if c else 'c')

但是如果我们在第一个or_test中启用lambda表达式,那么Python也可以将它解析为:

(lambda a, b: 'a') if a else 'b' if c else 'c'

这本身并不是本身错误,但Python的设计者选择了前者对后者的解释。重要的是只能有一个解释,否则两个人可以使用不同的解释器运行相同的Python程序,并获得不同的结果。