Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I've recently become quite taken with conditional expressions in Python. Apparently some people consider it unpythonic and whether or not conditional/ternary expressions are even A Good Thing seems to be up for debate -- but I've been digging them lately.

x if C else y

So far I've noted there are two ways Python will appear to 'let' you use this syntax, though I only see a pointer to the first in its official docs, so I'm a little uncertain if the second method (which I've not used, yet) is considered a good practice or not.

The first, being:

myvariable = x if C else y ##also, "return x if C else y"

Seems fairly common; one finds it in JavaScript and Ruby and basically any other language where you'd be impelled to drop a one-liner instead of three lines of

if C:
    myvariable = x
else:
    myvariable = y

However, I do see that Python will let you 'get away' with a line such as this, without assigning anything:

foo() if C else bar()

I'm a fairly new programmer, really, and so I try to hesitate implementing the wrong tool for the job. This to me looks like an interesting method for controlling the flow of a program, if not the typical way for doing so. For example, if we get the high score on Stick's Asteroid's Clone v.001:

record_score() if currentscore > highestscore else display_scores()

I find it readable (others may not) and descriptive. However, in my non-exhaustive independent research of being able to use conditional expressions in a way besides assignment, I don't really see a whole lot of precedent for it. That leads me to think that one wouldn't really use it in this way in the first place, regardless of the language you're in, because it just isn't the right way to handle the state of your program.

Additionally, I recognize that the difference between a 'good' implementation of this and a 'bad' one may just be to make use of return and reconsider the relevant code.

return record_score if currentscore > highestscore else display_scores ##and then the state machine takes over

That's fine too, but the question still stands in my mind if the suggested wording would ever be acceptable in the first place.

So I ask, is it even good practice to use conditional expressions apart from assignment? Or to put a finer point on it, is it acceptable to use it as a means of controlling the flow of a program?

share|improve this question

3 Answers 3

up vote 2 down vote accepted

In general, ternary if/else statements in Python are used to shortcut simple statements, as you mention in your question. They save three lines of code and are more transparent than Boolean operators and and or (especially when the latter two are combined). They are used for assignments, and they can also be used in other ways such as in list comprehensions:

['odd' if i % 2 else 'even' for i in range(10)]
['even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd']

'odd' if i % 2 else 'even' is technically a ternary if/else statement rather than part of list comprehension syntax per se.

Regarding your question about calling a function with a ternary if/else statement, I find that usage to be a little more difficult to manage from the standpoint of readability. Often if I see a function call at the beginning of a line, I don't usually suspect that another function may be hiding in its wings further to the right. I may very well miss that fact on the first pass and be left wondering how a function was called only to find out that it was called at the end of a line with a ternary if/else statement.

That being said, calling a function with a ternary if/else statement might be more natural in something like a list comprehension or a generator expression, where I am already reading through the line in order to process what is taking place. In these cases, however, map() is usually a better way to go performance-wise, so the point may be moot.

Using it in a return statement might also be more natural, since I expect these lines to be statements and because they are so important. But I don't see ternary if/else statements used in return statements all that often.

At the end of the day, I would prefer not to use ternary if/else statements as a means to control the flow of a program, since the ternary if/else statement can push important details to a place of less prominence. I would prefer to use them in scenarios where they preserve space and are relatively simple. (In this regard, they are somewhat like list comprehensions, which sometimes can be abused; list comprehensions sometimes contain very complex logic and become a nightmare for others to maintain down the road.) But ternary if/else statements still have a variety of simpler uses, for which I am often grateful.

share|improve this answer

Ternary operators are acceptable in a minority of cases, where the reduced lines of code outweighs the additional complexity of having the branch. This means it works well in list comprehensions or lambdas where the reader is expecting more complexity, but it would harm readability if it is used in place of a normal if/else statement, as the reader is likely not expecting a branch.

In my opinion, Python ternary statements are slightly worse than usual though, because they do not take the conventional form. For this reason, I would avoid ternary statements in more places than in other languages. Try to spot the odd one out:

Conventional branch:
if <cond> then <true-val> else <false-val>

C ternary:
<cond> ? <true-val> : <false-val>

Python ternary:
<true-val> if <cond> else <false-val>

Some people prefer the Python ternary because it is more natural to the way they think, but obviously this varies among people, so I do not prefer it for the simple reason that it doesn't conform to the expected <cond>/<true-val>/<false-val> order.

Of course, there are several ways of doing ternary statements in Python, but they get weirder and I would not recommend them more than the standard Python ternary, e.g.:

Tuple trick:
(<false-val>, <true-val>)[<cond>]

Boolean trick:
<cond> and <true-val> or <false-val>

I wouldn't re commend the last one, even though the operands are in the expected order, because it is non-intuitive for those not well-versed in Boolean algebra.

share|improve this answer

The two expressions put emphasis on different things. The common expression

if C then x else y

puts emphasis on C and sets x and y on an equal foot, while

x if C else y

highlights x and lets C and y on the side, implying a lesser importance than x has.

As a programmer, you then need to decide what is more important, of x or C.

I would for instance use the first form in the following contexts:

  • A process forked and C tells if we are in the parent or the child.
  • A security policy is being implemented and C tells if we are operating with appropriate privileges.
  • A request has been sent to a peer and C tells if it succesfully completed.
  • A recursive function is being written and C tells if the recurrence stops.

These are cases where I would want to put emphasis on the conditional C either because I think it is really governing the logic or because I expect other persons reading the code to think so. In the latter case, you can think about the idiom as to a cliché, which fits mostly because it is expected there.

I would for instance use the second form in the following contexts:

  • A variables might need initialisation and C tells if it is actually the case.
  • A system resource should be deallocated, if has not already been.

These are cases where I would recognise x as the common case and y as a marginal case. This is only a rule of thumb, however, because in recursing functions the recurrence is the common case, still the emphasis should be put on the recurrence condition.

Which one to use is a matter of style, either yours or the style used by the community you are working with. If you are new to programming, it is fine to let your style maturate. Give yourself time.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.