所以我偶然发现python中元组的特定行为,我想知道是否有特定的原因发生了。
虽然我们完全有能力在没有变量的情况下为变量赋值 明确地将其括在括号中:
>>> foo_bar_tuple = "foo","bar"
>>>
我们无法打印或签入包含变量的条件if语句 以前的方式的元组(没有明确地键入括号):
>>> print foo_bar_tuple == "foo","bar"
False bar
>>> if foo_bar_tuple == "foo","bar": pass
SyntaxError: invalid syntax
>>>
>>> print foo_bar_tuple == ("foo","bar")
True
>>>
>>> if foo_bar_tuple == ("foo","bar"): pass
>>>
有人为什么? 在此先感谢,虽然我没有找到任何类似的主题,但如果您认为这是一个可能的公告,请通知我。 干杯, 亚历
答案 0 :(得分:7)
这是因为用逗号分隔的表达式在整个逗号分隔的元组之前被评估(这是Python语法术语中的“表达式列表”)。因此,当您执行foo_bar_tuple=="foo", "bar"
时,会将其解释为(foo_bar_tuple=="foo"), "bar"
。 the documentation中描述了此行为。
如果你只是自己编写这样一个表达式,你可以看到这个:
>>> 1, 2 == 1, 2 # interpreted as "1, (2==1), 2"
(1, False, 2)
未加密码化的元组的SyntaxError是因为未加粗体的元组在Python语法中不是“原子”,这意味着它不能作为if
条件的唯一内容。 (您可以通过追踪the grammar来自行验证。)
答案 1 :(得分:4)
在[{3}}之后考虑if 1 == 1,2:
应该导致SyntaxError
的示例:
if 1 == 1,2:
使用if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
,我们可以转移if
关键字并开始解析1 == 1,2:
对于test
规则,只有第一次生产匹配:
test: or_test ['if' or_test 'else' test] | lambdef
然后我们得到:
or_test: and_test ('or' and_test)*
然后进入and_test
:
and_test: not_test ('and' not_test)*
此处我们暂时进入not_test
:
not_test: 'not' not_test | comparison
注意,我们的输入是1 == 1,2:
,因此第一个产品不匹配,我们检查另一个:(1)
comparison: expr (comp_op expr)*
继续踩下(我们只选择第一个非终端,因为零或更多的星需要我们输入中根本没有的终端):
expr: xor_expr ('|' xor_expr)*
xor_expr: and_expr ('^' and_expr)*
and_expr: shift_expr ('&' shift_expr)*
shift_expr: arith_expr (('<<'|'>>') arith_expr)*
arith_expr: term (('+'|'-') term)*
term: factor (('*'|'/'|'%'|'//') factor)*
factor: ('+'|'-'|'~') factor | power
现在我们使用power
制作:
power: atom trailer* ['**' factor]
atom: ('(' [yield_expr|testlist_comp] ')' |
'[' [testlist_comp] ']' |
'{' [dictorsetmaker] '}' |
NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False')
并在我们的输入中转移NUMBER
(1
)并减少。现在我们回到(1),输入==1,2:
来解析。 ==
匹配comp_op
:
comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'
所以我们转移并减少,留下输入1,2:
(当前解析输出为NUMBER comp_op
,我们现在需要匹配expr
)。我们重复左侧的过程,直接进入atom
非终端并选择NUMBER
制作。转移并减少。
由于,
与comp_op
不匹配,我们会减少test
非终端并接收'if' NUMBER comp_op NUMBER
。我们现在需要匹配else
,elif
或:
,但我们有,
因此我们失败了SyntaxError
。
答案 2 :(得分:2)
I think the operator precedence table summarizes this nicely:
你会看到比较在表达式之前进行,这些表达式实际上已经死了。
in, not in, is, is not, Comparisons, including membership tests
<, <=, >, >=, <>, !=, == and identity tests
...
(expressions...), [expressions...], Binding or tuple display, list display,
{key: value...}, `expressions...` dictionary display, string conversion