'Python Ternary Conditional Operator'

Posted on Sat 23 March 2019 in python

There is no true ternary operator with Python; not like what can be used with Java or C.

result = testCondition ? value1 : value2
minVal = a < b ? a : b;

There is, however, a feature that brings ternary-like tests to Python. A tuple and “index into the tuple,” may be used. For example a database is queried, and we need to print a particular field to the screen.

print({} : {}.format(value.name, value.comments))

That works, until value.comments is null or None. Then the following error is received:

TypeError: unsupported format string passed to NoneType.__format__

At this point, one should test to see if value.comments is None. Example:

if value.comments is None:
    comments = None
else:
    comments = value.comments

That works, but it is determined that the user wants a few more field to be displayed. Example:

print("{: <10} {: >5} {: >10} {: >10} {: >15}".format(value.name, value.
gid, value.auth, value.domain, value.comments))

The name, gid and domain are never null or None, since they are required fields, but comments and auth can be blank. One could have two if/else statements, however, here is a ternary look-a-like.

my_value = (falseValue, trueValue)[test]

How does it work?

Since “True” equals 1, then if the test is True, the index of our tuple is 1, which gives us trueValue.

my_value = (falseValue, trueValue)[1]

Conversely, if the test is False (a value of 0), then the index is 0 and we get falseValue.

my_value = (falseValue, trueValue)[0]

Instead of this:

for value in db.get_data(domain=domain):
    if value.auth is None:
        auth = "None"
    else:
auth = value.auth
    if value.comments is None:
        comments = "No Comment"
    else:
        comments = value.comments
    print("{: <10} {: >5} {: >10} {: >10} {: >15}".format(value.name,
value.gid, auth, value.domain, comment))

We have this:

for value in db.get_data(domain=domain):
    auth = (value.auth, "None")[value.auth is None]
    comment = (value.comments, "No Comment")[value.comments is None]
    print("{: <10} {: >5} {: >10} {: >10} {: >15}".format(value.name,
value.gid, auth, value.domain, comment))

The code is more elegant and easier to understand. Though this example is simple, if one needed to test numerous things, a messy nest of if /else can be made over into a clean workable, easy to read code.

A little more of "how it works"

Python 3.6.3 (default, Oct 30 2017, 11:15:33)
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.37)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> True == 1
True
>>> True == 2
False
>>> False == 0
True
>>> False == 3
False
>>>
>>>
>>> au = None
>>> au1 = "something"
>>> au2 = "else"
>>> x = (au1, au2)
>>> x
('something', 'else')
>>> x[True]
'else'
>>> x[False]
'something'