One common role for the prior section’s Boolean operators is to code an expression that runs the same as an if statement. Consider the following statement, which sets A to either Y or Z, based on the truth value of X:
if X:
A = Y
else:
A = Z
Sometimes, though, the items involved in such a statement are so simple that it seems like overkill to spread them across four lines. At other times, we may want to nest such a construct in a larger statement instead of assigning its result to a variable. For these reasons (and, frankly, because the C language has a similar tool), Python 2.5 introduced a new expression format that allows us to say the same thing in one expression:
A = Y if X else Z
This expression has the exact same effect as the preceding four-line if statement, but it’s simpler to code. As in the statement equivalent, Python runs expression Y only if X turns out to be true, and runs expression Z only if X turns out to be false. That is, it short-circuits, just like the Boolean operators described in the prior section, running just Y or Z but not both. Here are some examples of it in action:
>>>A = 't' if 'spam' else 'f'# For strings, nonempty means true >>>A't' >>>A = 't' if '' else 'f'>>>A'f'
Prior to Python 2.5 (and after 2.5, if you insist), the same effect can often be achieved by a careful combination of the and and or operators, because they return either the object on the left side or the object on the right as the preceding section described:
A = ((X and Y) or Z)
This works, but there is a catch—you have to be able to assume that Y will be Boolean true. If that is the case, the effect is the same: the and runs first and returns Y if X is true; if X if false the and skips Y, and the or simply returns Z. In other words, we get “if X then Y else Z.” This is equivalent to the ternary form:
A = Y if X else Z
The and/or combination form also seems to require a “moment of great clarity” to understand the first time you see it, and it’s no longer required as of 2.5—use the equivalent and more robust and mnemonic if/else expression when you need this structure, or use a full if statement if the parts are nontrivial.
As a side note, using the following expression in Python is similar because the bool function will translate X into the equivalent of integer 1 or 0, which can then be used as offsets to pick true and false values from a list:
A = [Z, Y][bool(X)]
For example:
>>>['f', 't'][bool('')]'f' >>>['f', 't'][bool('spam')]'t'
However, this isn’t exactly the same, because Python will not short-circuit—it will always run both Z and Y, regardless of the value of X. Because of such complexities, you’re better off using the simpler and more easily understood if/else expression as of Python 2.5 and later. Again, though, you should use even that sparingly, and only if its parts are all fairly simple; otherwise, you’re better off coding the full if statement form to make changes easier in the future. Your coworkers will be happy you did.
Still, you may see the and/or version in code written prior to 2.5 (and in Python code written by ex–C programmers who haven’t quite let go of their dark coding pasts).[29]
[29] In fact, Python’s Y if X else Z has a slightly different order than C’s X ? Y : Z, and uses more readable words. Its differing order was reportedly chosen in response to analysis of common usage patterns in Python code. According to the Python folklore, this order was also chosen in part to discourage ex–C programmers from overusing it! Remember, simple is better than complex, in Python and elsewhere. If you have to work at packing logic into expressions like this, statements are probably your better bet.