What are the operator methods for boolean 'and

2019-02-25 03:51发布

问题:

For instance, these are defined in the operator module and can be used as such:

import operator
print operator.__add__   # alias add -> +
print operator.__sub__   # alias sub -> -
print operator.__and__   # alias and_ -> &
print operator.__or__    # alias or_ -> |

Then what is the equivalent of and and or?

print operator."and ?????"  # should be boolean-and
print operator."or ????"    # should be boolean-or

回答1:

These do not exist. The best you can do is to replace them with a lambda:

band = (lambda x,y: x and y)
bor = (lambda x,y: x or y)

The reason is you can not implement the complete behavior of and or or because they can short circuit.

E.G:

if variable or long_fonction_to_execute():
    # do stuff

If variable is True, the long_fonction_to_execute will never be called because Python knows than or has to return True anyway. It's an optimization. It's a very desirable feature most of the time, as it can save a lot of useless processing.

But it means you cannot make it a function:

E.G:

if bor(variable, long_fonction_to_execute()):
    # do stuff

In that case, long_fonction_to_execute is called even before being evaluated.

Luckily, you rarely need something like that given the fact that you an use generators and list comprehensions.



回答2:

The and and or operators don't have an equivalent in the operator module, because they can't be implemented as a function. This is because they are short-circuiting: they may not evaluate their second operand depending on the outcome of the first.



回答3:

Extension of e-satis's answer:

lazyand = (lambda x,y: x() and y())
lazyor = (lambda x,y: x() or y())

The difference here is the conditions passed in are themselves thunks (functions of the form "() -> value") which are only evaluated as needed. (It could be argued that only y needs to be lazily evaluated, but I wrote it as such for consistency).

That is, this preserves the "lazy" aspect of and (and or) at the expense of more verbose code and more objects/method invocations.

andexpr = lazyand(lambda: false, lambda: never_executed())
andexpr() # false

I would be hard pressed to actually recommend using this approach though - it is important to note that these thunks must be explicit, as shown above. This might be one reason it was not included in the operator module. Some other languages allow pass-by-name or implicit "lifting".

Happy coding.