Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python or on operator module [duplicate]

On the operator module, we have the or_ function, which is the bitwise or (|).

However I can't seem to find the logical or (or).

The documentation doesn't seem to list it.

I'm wondering why isn't it included? Is it not considered a operator?

Is there a builtin function that provides its behaviour?

like image 839
loopbackbee Avatar asked Mar 13 '14 16:03

loopbackbee


3 Answers

The or operator short circuits; the right-hand expression is not evaluated when the left-hand returns a true value. This applies to the and operator as well; when the left-hand side expression returns a false value, the right-hand expression is not evaluated.

You could not do this with a function; all operands have to be evaluated before the function can be called. As such, there is no equivalent function for it in the operator module.

Compare:

foo = None
result = foo and foo(bar)

with

foo = None
result = operator.boolean_and(foo, foo(bar))  # hypothetical and implementation

The latter expression will fail, because you cannot use None as a callable. The first version works, because the and operator won't evaluate the foo(bar) expression.

like image 148
Martijn Pieters Avatar answered Oct 01 '22 08:10

Martijn Pieters


The closest thing to a built-in or function is any:

>>> any((1, 2))
True

If you wanted to duplicate or's functionality of returning non-boolean operands, you could use next with a filter:

>>> next(operand for operand in (1, 2) if operand)
1

But like Martijn said, neither are true drop-in replacements for or because it short-circuits. A true or function would have to accept functions to be able to avoid evaluating all the results:

logical_or(lambda: 1, lambda: 2)

This is somewhat unwieldy, and would be inconsistent with the rest of the operator module, so it's probably best that it's left out and you use other explicit methods instead.

like image 30
nmclean Avatar answered Oct 02 '22 08:10

nmclean


It's not possible:

This can explicitly be found in the docs:

The expression x or y first evaluates x; if x is true, its value is returned; otherwise, y is evaluated and the resulting value is returned.

It does not exist as an operator function because due to the language specification, it is impossible to implement because you cannot delay execution of a called argument when calling the function. Here is an example of or in action:

def foo():
    return 'foo'

def bar():
    raise RuntimeError

If bar is called, we get a Runtime error. And looking at the following line, we see that Python shortcuts the evaluation of the line, since foo returns a True-ish value.

>>> foo() or bar()
'foo'

We can approximate:

We can simulate this behavior by passing in uncalled functions, and then calling them inside our or function:

def my_or(*funcs):
    for func in funcs:
        call = func()
        if call:
            return call
    return call

>>> my_or(foo, bar)
'foo'

But you cannot shortcut execution of called callables that are passed to a function:

>>> my_or(foo, bar())

Traceback (most recent call last):
  File "<pyshell#28>", line 1, in <module>
    like_or(foo, bar())
  File "<pyshell#24>", line 2, in bar
    raise RuntimeError
RuntimeError

So it would be improper to include such a function in the built-ins or standard library because users would expect an or function to work just as a boolean or test, which again, is impossible.

like image 21
Russia Must Remove Putin Avatar answered Oct 02 '22 08:10

Russia Must Remove Putin