Does Python support short-circuiting?

后端 未结 3 1967
夕颜
夕颜 2020-11-21 08:47

Does Python support short-circuiting in boolean expressions?

3条回答
  •  野趣味
    野趣味 (楼主)
    2020-11-21 09:35

    Short-circuiting behavior in operator and, or:

    Let's first define a useful function to determine if something is executed or not. A simple function that accepts an argument, prints a message and returns the input, unchanged.

    >>> def fun(i):
    ...     print "executed"
    ...     return i
    ... 
    

    One can observe the Python's short-circuiting behavior of and, or operators in the following example:

    >>> fun(1)
    executed
    1
    >>> 1 or fun(1)    # due to short-circuiting  "executed" not printed
    1
    >>> 1 and fun(1)   # fun(1) called and "executed" printed 
    executed
    1
    >>> 0 and fun(1)   # due to short-circuiting  "executed" not printed 
    0
    

    Note: The following values are considered by the interpreter to mean false:

            False    None    0    ""    ()    []     {}
    

    Short-circuiting behavior in function: any(), all():

    Python's any() and all() functions also support short-circuiting. As shown in the docs; they evaluate each element of a sequence in-order, until finding a result that allows an early exit in the evaluation. Consider examples below to understand both.

    The function any() checks if any element is True. It stops executing as soon as a True is encountered and returns True.

    >>> any(fun(i) for i in [1, 2, 3, 4])   # bool(1) = True
    executed
    True
    >>> any(fun(i) for i in [0, 2, 3, 4])   
    executed                               # bool(0) = False
    executed                               # bool(2) = True
    True
    >>> any(fun(i) for i in [0, 0, 3, 4])
    executed
    executed
    executed
    True
    

    The function all() checks all elements are True and stops executing as soon as a False is encountered:

    >>> all(fun(i) for i in [0, 0, 3, 4])
    executed
    False
    >>> all(fun(i) for i in [1, 0, 3, 4])
    executed
    executed
    False
    

    Short-circuiting behavior in Chained Comparison:

    Additionally, in Python

    Comparisons can be chained arbitrarily; for example, x < y <= z is equivalent to x < y and y <= z, except that y is evaluated only once (but in both cases z is not evaluated at all when x < y is found to be false).

    >>> 5 > 6 > fun(3)    # same as:  5 > 6 and 6 > fun(3)
    False                 # 5 > 6 is False so fun() not called and "executed" NOT printed
    >>> 5 < 6 > fun(3)    # 5 < 6 is True 
    executed              # fun(3) called and "executed" printed
    True
    >>> 4 <= 6 > fun(7)   # 4 <= 6 is True  
    executed              # fun(3) called and "executed" printed
    False
    >>> 5 < fun(6) < 3    # only prints "executed" once
    executed
    False
    >>> 5 < fun(6) and fun(6) < 3 # prints "executed" twice, because the second part executes it again
    executed
    executed
    False
    

    Edit:
    One more interesting point to note :- Logical and, or operators in Python returns an operand's value instead of a Boolean (True or False). For example:

    Operation x and y gives the result if x is false, then x, else y

    Unlike in other languages e.g. &&, || operators in C that return either 0 or 1.

    Examples:

    >>> 3 and 5    # Second operand evaluated and returned 
    5                   
    >>> 3  and ()
    ()
    >>> () and 5   # Second operand NOT evaluated as first operand () is  false
    ()             # so first operand returned 
    

    Similarly or operator return left most value for which bool(value) == True else right most false value (according to short-circuiting behavior), examples:

    >>> 2 or 5    # left most operand bool(2) == True
    2    
    >>> 0 or 5    # bool(0) == False and bool(5) == True
    5
    >>> 0 or ()
    ()
    

    So, how is this useful? One example use given in Practical Python By Magnus Lie Hetland:
    Let’s say a user is supposed to enter his or her name, but may opt to enter nothing, in which case you want to use the default value ''. You could use an if statement, but you could also state things very succinctly:

    In [171]: name = raw_input('Enter Name: ') or ''
    Enter Name: 
    
    In [172]: name
    Out[172]: ''
    

    In other words, if the return value from raw_input is true (not an empty string), it is assigned to name (nothing changes); otherwise, the default '' is assigned to name.

提交回复
热议问题