## Ternary/Conditional Expressions

A place where you can post Python-related tutorials you made yourself, or links to tutorials made by others.

### Ternary/Conditional Expressions

If you have ever required a simple if/else statement in your code then conditional expressions might be of interest to you.

The standard if/else statement might look like this:
Code: Select all
`if eggs:    mystring = "Spam and eggs."else:    mystring = "Spam and spam."`
I know that when I have to do such things I often lament that I needed four lines (or two if you put the statement on the same line as the colon) to do so.

In these cases one can use what is called a ternary or conditional expression (py2.5 and later according to documentation).
With this statement the previous code becomes:
Code: Select all
`mystring = "Spam and eggs." if eggs else "Spam and spam."`
This allows us to one-line our simple if/else statement.

Now I personally love this syntax, but it should obviously be used with some discretion. It is very easy to make an extremely long incomprehensible statement using this syntax. Apparently some Python programmers seem to think it should be avoided, but I tend to disagree. That said, I often default to it when there is a better alternative and have to catch myself. Essentially, be certain that it is actually making things easier when you use it; not more convoluted.

Now if you are comfortable with the syntax of such expressions, it is natural to ask if you can use it with the augmented assignment operators. The answer here is yes, but again, it is quite easy to make something that isn't particularly readable when doing so.

Here is an example:
Code: Select all
`a += 1 if b%2 else 2`
Now what exactly is this code saying?
It is telling us to increment the value of a by 1 if b is odd. If b is even, increment the value of a by 2. Is this the clearest way to write this statement? I don't know. If you are unsure if it is clear, don't use it. If you do decide to use the ternary expression with augmented assignment operators just be aware that the final value after the else will be evaluated using the same augmented assignment operator.

So our previous statement is equivalent to:
Code: Select all
`if b%2:    a+=1else:    a+=2`

Notice also that our operator is only typed at the beginning of the ternary expression. If you write:
Code: Select all
`a+=1 if b%2 else a+=2`
while you may think that this is clearer, it won't work. When we use the ternary operator there are still two sides of the statement; The name to be assigned to, and the value (which in this case is conditional) being assigned. As this is the case, for clarity's sake I often find it is much clearer to write the statement as:
Code: Select all
`a += (1 if b%2 else 2)`
These parenthesis while not necessary, I find make the intention of the statement much clearer.

For more information on the subject here is the original PEP in which it was added: PEP 308
And for more on the ternary operator/expression in general see the wiki page: Ternary Operators ?:

If anyone has any additional thing to add on this subject, or foreboding warnings to programmers not to use it, please voice them. Also if you have any additional examples that you might feel are more illustrative of its uses please share them.

Cheers,
-Mek
(Edit: Slight edit for clarity; spaces added in the augmented assignment ternary example.)
Last edited by Mekire on Thu Feb 21, 2013 11:39 pm, edited 1 time in total.
• Use code tags when posting code.
• Include any errors with your post (in code tags).
• Make examples the minimum length to demonstrate your issue.

Mekire

Posts: 1501
Joined: Thu Feb 07, 2013 11:33 pm
Location: Tucson, Arizona

### Re: Ternary/Conditional Expressions

Apparently some Python programmers seem to think it should be avoided

I am one of these programmers. One reason is when i scan code, and often miss an else/elif clause. I find the standard more structured, and noticeable. Now i like how python makes things condensed compared to other languages. But in some cases that feature turns into hinderance. This is also the reason i tend to stay away from list comps. I find it looks more cluttered. Even though its a little faster, i like the more readable standard approach. But thats just my option. Good post though!
OS Ubuntu 14.04, Arch Linux, Gentoo, Windows 7/8
https://github.com/metulburr
steam

metulburr

Posts: 1844
Joined: Thu Feb 07, 2013 4:47 pm
Location: Elmira, NY

### Re: Ternary/Conditional Expressions

Haha. Thankyou. I also love comprehensions. I think the time I spent doing some of the problems on Project Euler ruined me though. I like to try to turn complex algorithms into one-liners whenever possible. I will be the first to admit that at its worst this certainly doesn't aid readability and is far from Pythonic.

One thing I forgot to add. I find that placing parenthesis like so:
Code: Select all
`a += (1 if b%2 else 2)`
can massively improve the readability of such conditional statements (especially those with augmented assignment ops).

-Mek
• Use code tags when posting code.
• Include any errors with your post (in code tags).
• Make examples the minimum length to demonstrate your issue.

Mekire

Posts: 1501
Joined: Thu Feb 07, 2013 11:33 pm
Location: Tucson, Arizona

### Re: Ternary/Conditional Expressions

A similar thing I sometimes do is use a boolean as an index for a len == 2 list. An example from this morning's bus ride:

Code: Select all
`det = ['a', 'an'][words[1][0] in 'aeiouh']`

Code: Select all
`if words[1][0] in 'aeiouh':   det = 'an'else:   det = 'a'`

Again, it is more concise but it hides the conditional that would otherwise be there.
Craig "Ichabod" O'Brien
Minimalist, buddhist, theist, and programmer
Current languages: Python, SAS, C++, Erlang
Previous serious languages: R, Java, VBA, Lisp, HyperTalk, BASIC
ichabod801

Posts: 310
Joined: Sat Feb 09, 2013 12:54 pm
Location: Outside Washington DC

### Re: Ternary/Conditional Expressions

I do use the ternary operator, although I just looked at my code to give an example and when I was reading it I realized the code was incorrect... so I certainly can't defend it!

ichabod that's terrible! (I've done it before too, but I learned better! Especially since there's a ternary operator now, if you really wanted to do that).

Mekire, in your original post, I find the spacing (or lack thereof) in the first ternary example to be very confusing, as it implies that the += occurs or 2 does, rather than the += being applied to the whole right hand side.
Join the #python-forum IRC channel on irc.freenode.net for off-topic chat!

Please prefer not to PM members. The point of the forum is so that anyone can benefit. We don't want to help you over PMs/emails/Skype chats that others can't benefit from

micseydel

Posts: 2032
Joined: Tue Feb 12, 2013 2:18 am
Location: Mountain View, CA

### Re: Ternary/Conditional Expressions

micseydel wrote:ichabod that's terrible!

It just seems that choosing between two values for a single variable is a waste of a good conditional.
Craig "Ichabod" O'Brien
Minimalist, buddhist, theist, and programmer
Current languages: Python, SAS, C++, Erlang
Previous serious languages: R, Java, VBA, Lisp, HyperTalk, BASIC
ichabod801

Posts: 310
Joined: Sat Feb 09, 2013 12:54 pm
Location: Outside Washington DC

### Re: Ternary/Conditional Expressions

The thing i don't like about ternaries in python is that it reads kinda backwards. I do like ternaries in other languages that use the ?:-syntax.

Lisp and scala do something neat because in those languages there is no difference between an if statements and an if-ternary.
You can just write:
Code: Select all
`(let a (if (zero? (rem b 2)) 2 1) ...)`

or
Code: Select all
`val a = if (b % 2 == 0) {2} else {1}`

Also, by the way, a feature that a future release of python could implement is a __call__-method in a boolean, such that one can do:
Code: Select all
`a = (b % 2 == 0)(2, 1)`

Lazy evaluation is still possible by using lambda's, so it becomes:
Code: Select all
`a = (b % 2 == 0)(lambda: 2, lambda: 1)()`

The closest syntax so far is:
Code: Select all
`a = [lambda: 2, lambda: 1][b % 2]()`