2

I am learning python using the excellent book by Mark Lutz. I come across this statement that the ternary operator in python, which is effectively this:

if a: 
   b
else: 
   c

can be written in 2 ways:

  1. b if a else c : using normal ternary syntax of python and

  2. ((a and b) or c) : using the equivalent but trickier and/or combination

I find the second representation disconcerting as it doesn't go well with my instinct. I tried these 2 syntax on the interactive prompt and found different answers for special case of b = 0. (assume b = 0, a = 4, c = 20)

  1. 0 if 4 else 20 outputs 0
  2. ((4 and 0) or 20) outputs 20

It appears that the 2 expressions are equivalents for all the truthy values of b but are not equivalent for all the falsy values of b.

I want to know, is there anything that I am missing here. Is my analysis wrong? Why does it say so in the book that the two cases are equivalent. Please enlighten my coarse mind. I am new to python. Thanks in advance.

4
  • No, you seem to have gotten it right. It must be the book you are reading, that is a bit vauge on when the second way is equal to the first. Commented Nov 7, 2018 at 5:46
  • 1
    No, you are right. You shouldn't use that, it is a dangerous for the reasons you've stated. Before the ternary operator, another idiom was [c, b][bool(a)], and if a is a boolean expression, you can omit the bool Commented Nov 7, 2018 at 6:50
  • @juanpa.arrivillaga This idiom [c,b][bool(a)] sounds cool and innovative. does it also fail for any such special cases? I hope not. Commented Nov 7, 2018 at 7:33
  • 1
    @Gsbansal10 it is not cool, it is hackey. Use the conditional expression, or the full conditional statement. Commented Nov 7, 2018 at 7:36

2 Answers 2

3

You are right, the second approach is great in most cases.

From the python docs:

Before this syntax was introduced in Python 2.5, a common idiom was to use logical operators: [expression] and [on_true] or [on_false]

Right after that they mention:

"However, this idiom is unsafe, as it can give wrong results when on_true has a false boolean value. Therefore, it is always better to use the ... if ... else ... form.

Here's a reference: https://docs.python.org/3.3/faq/programming.html#is-there-an-equivalent-of-c-s-ternary-operator

Adding brief sample per request:

a = True
b = False
c = True

# prints False (for b) correctly since a is True
if a:
   print b
else: 
   print c

# prints False (for b) correctly since a is True
print b if a else c 

# prints True (for c) incorrectly since a is True and b should have been printed
print ((a and b) or c) 
Sign up to request clarification or add additional context in comments.

3 Comments

Can you give an example code of when the grouped statement would fail?
sure, added a brief example :)
Much better! Awesome.
1

The perspective of the author here is different which should be considered. Let me try to explain with the code & inline comments:

#This if condition will get executed always(because its TRUE always for any number) except when it is '0' which is equivalent to boolean FALSE.
#'a' is the input which the author intends to show here. 'b' is the expected output
if a: 
   print(b)
else: 
   print(c)

#equivalent
print(b) if a else print(c) 
print((a and b) or c)

You are supposed to change the input and check the output. Whereas, you change the OUTPUT directly and try to check the output, which is not working. So, you are testing the wrong way is my opinion. The input here is a. Output here is b. Case 1: b = 12 a = 1 c = 20

*Case 2:
b = 12
a = 0
c = 20*
*Dont change 'b'. Change only 'a' and test is the conceptual idea. Coz, 'b' is the output.*

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.