1 minute read

我本来只想记录下 short-circuit operations,但是 chained comparisons 我很少写,这里一并记录下。

1. Chained Comparisons

From The Python Language Reference » 6.10. Comparisons:

Formally, if a, b, c, …, y, z are expressions and op1, op2, …, opN are comparison operators, then a op1 b op2 c ... y opN z is equivalent to (a op1 b) and (b op2 c) and ... (y opN z), except that each expression is evaluated at most once.

2. Short-circuit Operations


2.1 Short-circuit Boolean Operations

x or yx and y 以及 not x 在语法上等价于:

def (x or y):
    # if x:
    #     return x
    # else:
    #     return y

    return x if x else y

def (x and y):
    # if x:
    #     return y
    # else:
    #     return x

    return y if x else x

def (not x):
    # if x:
    #     return False
    # else:
    #     return True

    return False if x else True


  • 只有 not 一定是返回 bool True/False
  • andor 返回的是 x, y 而不是 bool(x), bool(y)
    • 这是我长久以来的误解

这使得 andor 有一种特殊的 assignment 的作用,比如:

def __init__(self, lst):
    self.lst = lst or []  # 如果 bool(lst) == False,则初始化为 [];否则初始化为 lst

2.2 Short-circuit all() and any()

这个好理解,因为 all() 语法上等价于:

def all(iterable):
    for element in iterable:
        if not element:
            return False
    return True

any() 语法上等价于:

def any(iterable):
    for element in iterable:
        if element:
            return True
    return False

2.3 Short-circuit Chained Comparisons

python 的 comparisons (<, >, ==, >=, <=, !=, is [not], [not] in) 一定返回 bool True/False


  1. chained comparisons 是 chained and operations
  2. each expression is evaluated at most once

就能很简单地判断 short-circuit 的场景,比如:

>>> def zero():
...     print("Calling zero()")
...     return 0

>>> def one():
...     print("Calling one()")
...     return 1

>>> 2 > one() > 0  # one() is evaluated only once
Calling one()  

>>> zero() > 2 > one()  # one() is short-circuited
Calling zero()