问题:Python中“ in”的关联性?
我正在制作一个Python解析器,这确实让我感到困惑:
>>> 1 in [] in 'a'
False
>>> (1 in []) in 'a'
TypeError: 'in <string>' requires string as left operand, not bool
>>> 1 in ([] in 'a')
TypeError: 'in <string>' requires string as left operand, not list
关于关联性等方面,“ in”在Python中到底如何工作?
为什么这些表达式中没有两个表现相同?
回答 0
1 in [] in 'a'
被评估为(1 in []) and ([] in 'a')
。
由于第一个条件(1 in []
)是False
,整个条件的评估为False
; ([] in 'a')
永远不会实际评估,因此不会引发任何错误。
这是语句定义:
In [121]: def func():
.....: return 1 in [] in 'a'
.....:
In [122]: dis.dis(func)
2 0 LOAD_CONST 1 (1)
3 BUILD_LIST 0
6 DUP_TOP
7 ROT_THREE
8 COMPARE_OP 6 (in)
11 JUMP_IF_FALSE 8 (to 22) #if first comparison is wrong
#then jump to 22,
14 POP_TOP
15 LOAD_CONST 2 ('a')
18 COMPARE_OP 6 (in) #this is never executed, so no Error
21 RETURN_VALUE
>> 22 ROT_TWO
23 POP_TOP
24 RETURN_VALUE
In [150]: def func1():
.....: return (1 in []) in 'a'
.....:
In [151]: dis.dis(func1)
2 0 LOAD_CONST 1 (1)
3 LOAD_CONST 3 (())
6 COMPARE_OP 6 (in) # perform 1 in []
9 LOAD_CONST 2 ('a') # now load 'a'
12 COMPARE_OP 6 (in) # compare result of (1 in []) with 'a'
# throws Error coz (False in 'a') is
# TypeError
15 RETURN_VALUE
In [153]: def func2():
.....: return 1 in ([] in 'a')
.....:
In [154]: dis.dis(func2)
2 0 LOAD_CONST 1 (1)
3 BUILD_LIST 0
6 LOAD_CONST 2 ('a')
9 COMPARE_OP 6 (in) # perform ([] in 'a'), which is
# Incorrect, so it throws TypeError
12 COMPARE_OP 6 (in) # if no Error then
# compare 1 with the result of ([] in 'a')
15 RETURN_VALUE
回答 1
Python通过链式比较来做特殊的事情。
对以下内容的评估不同:
x > y > z # in this case, if x > y evaluates to true, then
# the value of y is being used to compare, again,
# to z
(x > y) > z # the parenth form, on the other hand, will first
# evaluate x > y. And, compare the evaluated result
# with z, which can be "True > z" or "False > z"
但是,在这两种情况下,如果第一个比较是False
,则不会查看语句的其余部分。
对于您的特殊情况
1 in [] in 'a' # this is false because 1 is not in []
(1 in []) in a # this gives an error because we are
# essentially doing this: False in 'a'
1 in ([] in 'a') # this fails because you cannot do
# [] in 'a'
同样为了说明上面的第一条规则,这些是评估为True的语句。
1 in [1,2] in [4,[1,2]] # But "1 in [4,[1,2]]" is False
2 < 4 > 1 # and note "2 < 1" is also not true
python运算符的优先级:http : //docs.python.org/reference/expressions.html#summary
回答 2
比较可以任意链接,例如,x <y <= z等于x <y和y <= z,除了y仅被评估一次(但在两种情况下,当x <y被发现时,z都不被评估。是假的)。
这意味着,x in y in z
!中没有关联性!
以下是等效的:
1 in [] in 'a'
# <=>
middle = []
# False not evaluated
result = (1 in middle) and (middle in 'a')
(1 in []) in 'a'
# <=>
lhs = (1 in []) # False
result = lhs in 'a' # False in 'a' - TypeError
1 in ([] in 'a')
# <=>
rhs = ([] in 'a') # TypeError
result = 1 in rhs
回答 3
简短的回答是,由于这里已经以良好的方式多次给出了一个较长的答案,那就是布尔表达式被短路了,如果进一步的评估不能使true变为false ,则布尔表达式 已停止评估。
(请参阅http://en.wikipedia.org/wiki/Short-circuit_evaluation)
答案可能有点短(没有双关语),但是如上所述,所有其他解释在这里都已经做得很好,但是我认为该词值得一提。