def isBig(x): if x > 4: return 'apple' else: return 'orange'
This works:
if isBig(y): return isBig(y)
This does NOT work:
if fruit = isBig(y): return fruit
Why doesn't the 2nd one work!? I want a 1-liner. Except, the 1st one will call the function TWICE.
How to make it 1 liner, without calling the function twice?
Yes, you can assign the value of variable inside if.
For example, assignment expressions using the := syntax allow variables to be assigned inside of if statements, which can often produce shorter and more compact sections of Python code by eliminating variable assignments in lines preceding or following the if statement.
Using the assignment operator in conditional expressions frequently indicates programmer error and can result in unexpected behavior. The assignment operator should not be used in the following contexts: if (controlling expression)
Should you define a variable inside IF statement? Honestly, there's no right or wrong answer to this question. JavaScript allows it, so you can make your decision from there.
Starting Python 3.8
, and the introduction of assignment expressions (PEP 572) (:=
operator), it's now possible to capture the condition value (isBig(y)
) as a variable (x
) in order to re-use it within the body of the condition:
if x := isBig(y): return x
I see somebody else has already pointed to my old "assign and set" Cookbook recipe, which boils down in its simplest version to:
class Holder(object): def set(self, value): self.value = value return value def get(self): return self.value h = Holder() ... if h.set(isBig(y)): return h.get()
However, this was intended mostly to ease transliteration between Python and languages where assignment is directly supported in if
or while
. If you have "hundreds" of such check-and-return in a cascade, it's much better to do something completely different:
hundreds = isBig, isSmall, isJuicy, isBlah, ... for predicate in hundreds: result = predicate(y) if result: return result
or even something like
return next(x for x in (f(y) for f in hundreds) if x)
if it's OK to get a StopIteration exception if no predicate is satisfied, or
return next((x for x in (f(y) for f in hundreds) if x)), None)
if None
is the proper return value when no predicate is satisfied, etc.
Almost invariably, using (or even wishing for;-) the Holder
trick/non-idiom is a "design smell" which suggests looking for a different and more Pythonic approach -- the one case where Holder
is justified is exactly the special case for which I designed it, i.e., the case where you want to keep close correspondence between the Python code and some non-Python (you're transliterating a reference algorithm in Python and want it working first before refactoring it into a more Pythonic form, or you're writing Python as a prototype that will be transliterated into C++, C#, Java, etc, once it's working effectively).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With