0

I can't understand how this condition behind the % works

for i in range(1,6): 
     print "pet%d" % (i == 1 and 2 or 4)

this part (i == 1 and 2 or 4) is what I cant understand. As far as I understand it does the same as a

if i == 1: 
    i = 2 
else: 
    i = 4

but how does the (i == 1 and 2 or 4) work especially with the %d % i formatting?

basilius
  • 57
  • 1
  • 4

4 Answers4

4

Read it as 2 if i == 1 else 4 using the python a if b else c or if i == 1 then 2 else 4

It gives 4 unless i == 1 returns true, then it gives 2:

pet2
pet4
pet4
pet4
pet4

This sort of boolean (ab)use is common in shell scripts:

Evaluating the boolean goes as follows:

If i == 1 is True, then we must test what is on the other side of the and. 2 is also true, so we exit early (as the or is already known to be true, returning the last value 2.

If i == 1 is False, we skip the other side of the and and evaluate the other side of the or, which is 4. 4 is true, so we return 4.

TemporalWolf
  • 6,474
  • 1
  • 26
  • 42
2

What you have is an example of short-circuiting with and and or.

We can add some parens to see how the expression is evaluated:

(((i == 1) and 2) or 4)

or: only evaluates the second argument if the first one is False

and: only evaluates the second argument if the first one is True

Which makes 2 the result of the evaluation when i is 1 (since 2 is truthy and the second operand of the or will not be evaluated), and 4 otherwise (since a False in the first operand of the and means the second operand of the or will be returned).

Moses Koledoye
  • 71,737
  • 8
  • 101
  • 114
1

About conditional statement:

In Python, some values can be evaluated kinda like True and False even if they are not boolean values:

For instance:

if []:
   print "this branch is never reached since it evaluates to False"
   print "due to the empty list"
if 0:
   print "same thing here"

(More info about how some data types are evaluated in a boolean expression here: http://getpython3.com/diveintopython3/native-datatypes.html#booleans)

Now, back to the following statement:

(i == 1 and 2 or 4)

Here we have a boolean expression as well. Dissecting the expression, we have the following:

(i == 1 and 2 or 4)
((i == 1) and 2) or (4) # This is the order of evaluation

Since 2 and 4 are not 0, they will always evaluate to True

Now, understanding the output: The output will be always 4 if i is different than 1.

The reason for this is because if i == 1 the returned value is 2. The value 2 is returned because it is not necessary to evaluate the whole expression 2 or 4 since the first part is evaluated to True.

On the other hand, if i is not 1, the value 4 has to be evaluated. Because 4 is not zero, it is evaluated to True.

This is why the output is always 4 if i is different than 1

About the "ternary" operator:

Python does not have a ternary operator like in Java/C/C++ (?:) but you have a similar effect using if-else:

# value a = <value if condition is true> if <condition> else <other value>
# Example
>>> a =  2 if 1 < 10 else 0
>>> a
2

Therefore, if you wanted to print values from the range function, you should use the following:

for i in range(1,6): 
    print "pet%d" % i

Or maybe, printing A for even numbers and B for odd numbers:

for i in range(1,6): 
    print "pet%s" % ("A" if i % 2 == 0 else "B")
  • 1
    Python's [`A if condition else B`](http://stackoverflow.com/a/394814/3579910) is the ternary operation. – TemporalWolf Dec 13 '16 at 00:25
  • _"Python does not have a ternary operator like in Java/C/C++ (?:) but you have a similar effect using if-else"_ – Jeanderson Candido Dec 13 '16 at 00:56
  • if-else is not a ternary operator like "?" and ":" in Java or other languages that have explicitly tokens for this purpose. In Python, the grammar was just extended to handle this statement. – Jeanderson Candido Dec 13 '16 at 01:07
-1

I might be wrong, but I know in javaScript when you say i == 1 and 2 or 4 it evaluates from left to right.

Thus the computer will determine if i == 2, and if it does, it will have a temp val of bits set to 1, and take that flag and bitwise AND it with 2, resulting in the value 2. Since the next expression is an OR, it will not compute that since the condition is true regardless, and the "and" operator short circuits. Thus 2 will print.

However if i != 2, then the first part will evaluate to false, and have a temp val of all 0 bits. Then, the or with 4 will change the value to 4 (a bitwise 0 with 4 returns 4), and so 4 will print.

I hope this makes sense! Let me know if you have any other questions.

  • Feel free to read up on Python's operator precedence. https://docs.python.org/3/reference/expressions.html#operator-precedence – OneCricketeer Dec 12 '16 at 21:09