4

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?

eMad
  • 998
  • 3
  • 13
  • 31
  • 3
    In your case just flip the conditions in your `if` block, because `x == 2` doesn't change anything – adarsh Nov 28 '14 at 12:48
  • In this case, just flip the conditions. – Martijn Pieters Nov 28 '14 at 12:49
  • you need to or between them which will evaluate the pop if x != 2 – SMA Nov 28 '14 at 12:51
  • 1
    FYI: in Java the second operand will not execute either if the first one is false - with logical `&&`. Looking at binary `&` has led you astray. – maksimov Nov 28 '14 at 12:51
  • I can Flip the conditions but what in case we've pop() called in both operands? – eMad Nov 28 '14 at 12:57
  • 1
    @maksimov. In Java, `&` and `&&` are both logical operators (when applied to boolean operands). The difference between the two is that `&&` uses short-circuit evaluation, and `&` does not. When applied to for example `int`s, `&` is of course a bitwise operation, but that is not the case here. – Hoopje Nov 28 '14 at 13:18
  • @Hoopje Thanks for clarifying this! In fairness it's been awhile since I've used any bitwise operators in Java, it's nice to get a refresher once in a while. Googled up the spec: http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.22.2 – maksimov Nov 28 '14 at 15:03
  • possible duplicate of [Strange if statement](http://stackoverflow.com/questions/29663428/strange-if-statement) – Basilevs Apr 16 '15 at 17:52

3 Answers3

3

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.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • 1
    By the way @eMAD, I don't think the & operator in Java does what you are describing. Absent some exotic overloading, what it is actually doing is a bitwise AND operation between two expressions. See this: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/op3.html – rchang Nov 28 '14 at 12:52
  • @rchang actually [link](http://stackoverflow.com/questions/7199666/difference-between-and-in-java) made me think this – eMad Nov 28 '14 at 12:56
  • Thanks @MartijnPieters but Explicitly evaluating this means Python doesn't have a solution for this! Though Python is famous for doing large things in few lines. But in this case NOT! – eMad Nov 28 '14 at 13:03
  • 1
    @eMAD: but it *does* have a solution; just restructure your test. If your code is failing because of short-circuiting you need to re-think your code instead of blaming the tools. – Martijn Pieters Nov 28 '14 at 13:07
  • 3
    @rchang. Java is not C or C++, where booleans are basically ints in disguise. In Java, operators can have different semantics when applied to different types. `&` applied to boolean operands is *not* a bitwise "and", it is a *logical* "and" without short-circuit evaluation. The operator `&` applied to operands of type `int` (for example) is a bitwise operation. – Hoopje Nov 28 '14 at 13:15
1

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.

Dunes
  • 37,291
  • 7
  • 81
  • 97
0

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().

Dev-an
  • 462
  • 2
  • 6
  • 1
    This doesn't actually work; `all([cond1, cond2])` *would* work (e.g. pass in a list). But it is a lot more verbose and less clear as to what you are doing compared to just storing `cond1` and `cond2` separately first. – Martijn Pieters Nov 28 '14 at 12:58