Compressing `x if x else y` statement in Python

Question:

I’m quite acquainted with Python’s ternary operator approach:

value = foo if something else bar

My question is very simple: without prior assignments, is there anyway to reference the term being evaluated in (if ...) from one of the return operands (... if or else ...)?

The motivation here is that sometimes I use expressions in if ... that are exactly what I’d like to have as result in the ternary operation; happens though that, for small expressions, there’s no problem repeating it, but for a bit longer expressions, it goes somewhat nasty. Take this as an example:

value = info.findNext("b") if info.findNext("b") else "Oompa Loompa"
Asked By: Rubens

||

Answers:

Don’t use if ... else at all. Instead, take advantage of Python’s coalescing operators.

value = info.findNext("b") or "Oompa Loompa"

There is no way to do this, and that’s intentional. The ternary if is only supposed to be used for trivial cases.

If you want to use the result of a computation twice, put it in a temporary variable:

value = info.findNext("b")
value = value if value else "Oompa Loompa"

Once you do this, it becomes clear that you’re doing something silly, and in fact the pythonic way to write this is:

value = info.findNext("b")
if not value:
    value = "Oompa Loompa"

And that’s actually 5 fewer keystrokes than your original attempt.

If you really want to save keystrokes, you can instead do this:

value = info.findNext("b") or "Oompa Loompa"

But that’s discouraged by many style guides, and by the BDFL.

If you’re only doing this once, it’s better to be more explicit. If you’re doing it half a dozen times, it’s trivial—and much better—to make findNext take an optional default to return instead of None, just like all those built-in and stdlib functions:

def findNext(self, needle, defvalue=None):
    # same code as before, but instead of return None or falling off the end,
    # just return defvalue.

Then you can do this:

value = info.findNext("b", "Oompa Loompa")
Answered By: abarnert

If you have python 3.8 or greater, you can use the := operator. In your example, it would look like

value = bb if (bb := info.findNext("b")) else "Oompa Loompa"
Answered By: arunkannawadi