Assign within if statement Python
Asked Answered
D

2

4

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?

Divisible answered 6/5, 2015 at 2:39 Comment(2)
The first way you have is fine. Just be sure to use if res is None if the returned value can be some other valid but falsey values (e.g. empty string).Kraal
What you're really looking for here is C-style if res=spam(): or if (ch=getch()) != EOF:, and Python doesn't have that. Python has good reasons for that; Swift has different good reasons for it; if you're designing a new language and, saving one line or 5 characters may well be worth if it there are no compelling reasons otherwise, but you may have compelling reasons otherwise.Enriqueenriqueta
R
9

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
Rodeo answered 23/7, 2021 at 18:43 Comment(2)
You forgot to mention the informal name given to this new operator, the "walrus operator".Jugate
this assigns match to the result of pattern.search(data). Would you be able to assign match to data in one line?Mothering
E
2

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.

Enriqueenriqueta answered 6/5, 2015 at 2:50 Comment(3)
Thanks, I guess I was optimistic about some syntactic sugar. The problem with allowing the called functions to take None is that, in other contexts, I want the same function to raise an error if None or another invalid type is received. Plus, in most cases, it's something like if re.match(some_pattern, text): do_something_with(re.match(some_pattern, text).group(1)). If forget the if condition and re.match() returns None the interpreter will let me know soon enough.Divisible
@Peter: Usually there's nothing wrong with letting the interpreter let you know (whether "you" means the except handler in your code, or the programmer who didn't consider the possibility that the value could be None and therefore didn't code for it).Enriqueenriqueta
@Peter: Meanwhile, if you only show us a meaningless toy example, you're only going to get "here are a half-dozen ways to do similar things; which one is appropriate in your real code depends on that real code"; if you show us a couple of real examples, we can show you the idiomatic way to deal with those examples.Enriqueenriqueta

© 2022 - 2024 — McMap. All rights reserved.