Why is operator module missing `and` and `or`?

后端 未结 4 1094
渐次进展
渐次进展 2021-01-22 05:04

operator module makes it easy to avoid unnecessary functions and lambdas in situations like this:

import operator

def mytest(op, list1, list2):
    ok = [op(i1,         


        
相关标签:
4条回答
  • 2021-01-22 05:17

    You can write these yourself, but you'll need to pass a function (e.g. lambda) for the second argument to prevent it from being evaluated at call time, assuming that the usual short-circuiting behavior is important to you.

    def func_or(val1, fval2):
        return val1 or fval2()
    
    def func_and(val1, fval2):
        return val1 and fval2()
    

    Usage:

    func_or(False, lambda: True)
    func_and(True, lambda: False)
    
    0 讨论(0)
  • 2021-01-22 05:23

    Python's and and or syntaxes cannot directly be mapped to functions. These syntaxes are lazy evaluated: If the result of the left part of the expression allows to know the value of the whole expression, the right part is skipped. Since they introduce flow control, their behavior cannot be reproduced using an operator. To reduce confusion, python have chosen to simply not provide these methods.

    georg gives a good example of a situation where and laziness matters:

     if obj is not None and obj.is_valid():
         ...
    

    Now, if you don't need lazy evaluation, you can use abarnert's answer implementation:

    def and_(a, b):
        return a and b
    
    def or_(a, b):
        return a or b
    

    Usage:

    >>> or_(False, True)
    >>> and_(True, False)
    

    If you need lazy evaluation, you can use kindall's answer implementation:

    def func_or(val1, fval2):
        return val1 or fval2()
    
    def func_and(val1, fval2):
        return val1 and fval2()
    

    Usage:

    >>> func_or(False, lambda: True)
    >>> func_and(True, lambda: False)
    

    Note: As mentioned in the comments, the functions operator.and_ and operator.or_ correspond to the bitwise operators & and |. See: https://docs.python.org/3/library/operator.html#mapping-operators-to-functions

    Note that the names operators.and and operators.or aren't used: and and or are Python keywords so it would be a syntax error.

    0 讨论(0)
  • 2021-01-22 05:24

    Because you cannot convert boolean operators into python functions. Functions always evaluate their arguments, and boolean operators do not. Adding and and or to the operators module would also require adding a special kind of functions (like lisp "macros") that evaluate their arguments on demand. Obviously, this is not something python designers ever wanted. Consider:

    if obj is not None and obj.is_valid():
        ....
    

    you cannot write this in a functional form. An attempt like

      if operator.xyz(obj is not None, obj.is_valid()) 
    

    will fail if obj is actually None.

    0 讨论(0)
  • 2021-01-22 05:33

    The reason there's no operator.and is that and is a keyword, so that would be a SyntaxError.

    As tgh435 explained, the reason there's no renamed and function in operator is that it would be misleading: a function call always evaluates its operands, but the and operator doesn't. (It would also be an exception to an otherwise consistent and simple rule.)


    In your case, it looks like you don't actually care about short-circuiting at all, so can build your own version trivially:

    def and_(a, b):
        return a and b
    

    Or, if you're just using it once, even inline:

    mytest(lambda a, b: a and b, [-1, 2, -3], [1, -2, 33])
    

    In some cases, it's worth looking at all (and, for or, any). It is effectively short-circuited and expanded to arbitrary operands. Of course it has a different API than the operator functions, taking a single iterable of operands instead of two separate operands. And the way it short-circuits is different; it just stops iterating the iterable, which only helps if you've set things up so the iterable is only evaluating things as needed. So, it's usually not usable as a drop-in replacement—but it's sometimes usable if you refactor your code a bit.

    0 讨论(0)
提交回复
热议问题