Nested conditional expressions in Python (and code golf)

September 20, 2013

Recently I had an occasion to use a nested (or chained) conditional expression. I haven't used conditional expressions much, so at first I just wrote out what struck me as the obvious way:

res = a.field1 if a.field1 else obj.field2 if obj else None

(The goal is to use a.field1 if it's got a value, obj.field2 if obj is there, and otherwise None.)

Then I paused to ask myself if this was going to have the right grouping of evaluation; testing said that it did, to my pleasant surprise. It's always nice when Python behaves the way I expected it to and my naive code works. That it happens so often is one of the reasons that I like Python so much.

While this nested conditional expression was the obvious way to write the expression (since I was converting it from what would otherwise be a nested if), it's possible to be more clever. The simple way is to get rid of the actual conditional expressions in favour of exploiting the side effects of or and and:

res = a.field1 or (obj and obj.field2) or None

(Given when I'm trying to do here this doesn't suffer from the usual problem of (ab)using and and or this way.)

Of course we can golf this code further:

res = a.field1 or getattr(obj, 'field2', None)

To my mind this is well over the line into excessively clever, partly because it mixes two different ways to refer to fields in the same expression. Even the first condensed version is not something I'm entirely happy with (partly because it's subtly different than the straightforward version using conditional expressions). So my initial version is going to stay in my code.

(I think I've basically recanted on my views about avoiding conditional expressions in Python by now. Time moves on and I get used to things.)

Comments on this page:

Doesn’t Python have ternaries?

res = a.field1 or (obj ? obj.field2 : None)

I find this one way clearer than any of your versions, plus its semantics are exactly identical to the nested conditionals.

By cks at 2013-09-21 17:24:19:

Conditional expressions are the Python version of ternaries. I suppose I could have written this as:

res = a.field1 or (obj.field2 if obj else None)

but I don't like that version as much, basically because of aesthetics. (Theoretically I don't need the brackets but I think it's less clear without them.)

Yes, presumably the parens wouldn’t be necessary in my version either, if that version were possible, but I’d put them in anyway to make it more easily skimmable. The version with a conditional expression needs them desperately. I must say I still like that better than the version with two nested conditionals and no parens… though I’m not a fan of either.

Written on 20 September 2013.
« Processes waiting for NFS IO do show in Linux %iowait statistics
An example of optimizing C in the face of undefined behavior »

Page tools: View Source, View Normal, Add Comment.
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Fri Sep 20 22:49:29 2013
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.