eMad
eMad

Reputation: 1008

Explicitly evaluate both conditions when using Boolean AND

I'm not that familiar with Python. From Java I know that in conditionals, if we want have both the operands of && evaluated, we use & instead. For example:

if ( x == 2 & y++ == 3)
    // do this

But I'm working in python 2.7 and I want to perform operation like:

if x == 2 and myList.pop() == 3:
    # do this

But both operands of and must execute.

In Python, the first comparison would be performed and if it was false, the 2nd comparison would be skipped. But I want both of them to execute even if first comparison returned False. Is there any solution for this in Python?

Upvotes: 4

Views: 1066

Answers (3)

Martijn Pieters
Martijn Pieters

Reputation: 1123002

You'd just execute the conditions first, before testing with and:

# explicitly execute the conditions first, compare the outcomes later
test1, test2 = x == 2, myList.pop() == 3
if test1 and test2:

For your case that can be simplified down to just the myList.pop() call:

# explicitly pop a value from myList, regardless of what x == 2 returns
myList_value = myList.pop()
if x == 2 and myList_value == 3:

Of course, you could also just have swapped the tests:

if myList.pop() == 3 and x == 2:

to ensure that the list.pop() method is always executed.

Otherwise, the & bitwise operator is overloaded for Python booleans just like it is in Java:

>>> from itertools import product
>>> for a, b in product([False, True], repeat=2):
...     print('{a!r:5} and {b!r:5}: {o1!r:5}    {a!r:5} & {b!r:5}: {o2!r:5}'.format(a=a, b=b, o1=a and b, o2=a & b))
... 
False and False: False    False & False: False
False and True : False    False & True : False
True  and False: False    True  & False: False
True  and True : True     True  & True : True 

And as such you can use it to avoid short-circuiting, but only if both operands are booleans:

>>> def foo():
...     print 'called!'
...     return False
... 
>>> def bar():
...     print 'also called!'
...     return False
... 
>>> foo() and bar()
called!
False
>>> foo() & bar()
called!
also called!
False

However, I'd consider making use of this unpythonic, and indicative of bad coding style. Restructure your code to not have to rely on this in the first place.

Upvotes: 3

Dunes
Dunes

Reputation: 40733

The & operator exists in python. It will call the __and__ magic method, which is meant to perform a bitwise and operation on the operands

eg.

assert 3 & 6 == 2
assert True & 3 == 1

x = 0
y = [3]
assert not(x == 2 & y.pop() == 3)
assert y == []

However, you want to test that two things are true, rather than doing a bitwise operation. You would be best off reordinging the clauses of the condition or executing the separate conditions before hand and testing afterwards.

Upvotes: 1

Dev-an
Dev-an

Reputation: 462

You can use python's built-in all() or any() functions to avoid short-circuit evaluation.

In order to achieve &, you can easily use all():

if (all([cond1, cond2])):
    ...

Likewise for |, you can use any().

Upvotes: 0

Related Questions