ars*_*jii 5

>>> 'a' in 'ab' == True
False
>>> ('a' in 'ab') == True
True
Run Code Online (Sandbox Code Playgroud)

让我们来看看第一个变体实际意味着什么:

>>> import dis
>>> def f():
...     'a' in 'ab' == True
... 
>>> dis.dis(f)
  2           0 LOAD_CONST               1 ('a')
              3 LOAD_CONST               2 ('ab')
              6 DUP_TOP             
              7 ROT_THREE           
              8 COMPARE_OP               6 (in)
             11 JUMP_IF_FALSE_OR_POP    23
             14 LOAD_GLOBAL              0 (True)
             17 COMPARE_OP               2 (==)
             20 JUMP_FORWARD             2 (to 25)
        >>   23 ROT_TWO             
             24 POP_TOP             
        >>   25 POP_TOP             
             26 LOAD_CONST               0 (None)
             29 RETURN_VALUE  
Run Code Online (Sandbox Code Playgroud)

如果你遵循字节码,你会发现这相当于'a' in 'ab' and 'ab' == True.

  • 在前两个LOAD_CONSTs之后,堆栈包括:
    • 'ab'
    • 'a'
  • 之后DUP_TOP,堆栈包括:
    • 'ab'
    • 'ab'
    • 'a'
  • 之后ROT_THREE,堆栈包括:
    • 'ab'
    • 'a'
    • 'ab'
  • 此时,in(COMPARE_OP)操作前两个元素,如'a' in 'ab'.这样做的结果(True)被存储在堆栈中,而'ab''a'被弹出.现在堆栈包括:
    • True
    • 'ab'
  • JUMP_IF_FALSE_OR_POP是短路and:如果此时堆栈顶部的值是False我们知道整个表达式将是False,所以我们跳过第二个即将到来的比较.但是,在这种情况下,最高值为True,因此我们弹出此值并继续进行下一次比较.现在堆栈包括:
    • 'ab'
  • LOAD_GLOBALload True,和COMPARE_OP(==)将其与剩余的堆栈项进行比较'ab',如'ab' == True.其结果存储在堆栈中,这是整个语句的结果.

(你可以在这里找到完整的字节码指令列表)

把它们放在一起,我们有'a' in 'ab' and 'ab' == True.

现在,'ab' == TrueFalse:

>>> 'ab' == True
False
Run Code Online (Sandbox Code Playgroud)

意思是整个表达式False.


Bri*_*ian 5

操作员链接工作.

'a' in 'ab' == True
Run Code Online (Sandbox Code Playgroud)

相当于

'a' in 'ab' and 'ab' == True
Run Code Online (Sandbox Code Playgroud)

看一看:

>>> 'a' in 'ab' == True
False
>>> ('a' in 'ab') == True
True
>>> 'a' in ('ab' == True)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: argument of type 'bool' is not iterable
>>> 'a' in 'ab' and 'ab' == True
False
Run Code Online (Sandbox Code Playgroud)

从上面链接的文档:

比较可以任意链接,例如,x <y <= z等于x <y和y <= z,除了y仅被评估一次(但在两种情况下,当x <y被发现时,根本不评估z是假的).

形式上,如果a,b,c,...,y,z是表达式而op1,op2,...,opN是比较运算符,则op1 b op2 c ... y opN z等效于op1 b和b op2 c和... y opN z,除了每个表达式最多被评估一次.

操作符链接的真正优点是每个表达式最多被评估一次.因此a < b < c,b只评估一次,然后比较第一次a和第二次(如果必要的话)c.

作为一个更具体的例子,让我们考虑一下表达式0 < x < 5.在语义上,我们的意思是说x在闭合范围[0,5].Python通过评估逻辑上等效的表达式来捕获它0 < x and x < 5.希望澄清操作员链接的目的.