'Assign within if statement Python

Is there a simpler alternative than

res = returns_value_or_none(arg)
if res:
    do_something_with(res)

or

if returns_value_or_none(arg):
    do_something_with(returns_value_or_none(arg))

One which combines the assignment and if conditional into one statement?



Solution 1:[1]

Often, what you have is already the best option.


You can always create a new scope to bind the value to a variable:

(lambda res: do_something_with(res) if res else None)(returns_value_or_none(arg))

But that's certainly not going to be more readable, or more Pythonic.


If you just want to save one line, you can do this:

res = returns_value_or_none(arg)
if res: do_something_with(res)

This is sometimes more readable, but usually it's a net loss.


Another way to deal with this would be to change do_something_with to accept None and do nothing. This isn't as common in Python as it is in, say, Smalltalk or Swift, but it definitely has its place sometimes.

It's hard to see why with a toy example like this, but if you're calling these functions 70 times, putting the check in one place, inside the function, instead of in 70 places, everywhere it's called, is an obvious win. (Especially since you'd probably put it in 68 places and forget the other 2.)


Last, but not least, in many cases the right answer is exceptions. Your do_something_with probably already raises if you pass None. And you could surely change returns_value_or_none to returns_value_or_raises.

Again, in this toy example, it'll just look like more code. But in real-life code, it often makes sense to put a whole block of code inside a try/except, and handle all the errors at once down at the end. Or even to let the exceptions percolate up to a higher level where they're easier to deal with.

Of course that isn't appropriate in every case; if you're expecting None to be a frequent and perfectly reasonable response, and just want to skip one step rather than abort the whole chain of operations, checking or passing through None is going to make a lot more sense than littering your code with small try blocks.

Solution 2:[2]

For Python 3.8+, PEP 572 introduces Assignment Expressions

This allows assigning to variables within an expression using the notation NAME := expr. It can be used within if statements, for example:

if (match := pattern.search(data)) is not None:
    # Do something with match

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 abarnert
Solution 2 mhudnell