How to assign a variable in an IF condition, and then return it?

前端 未结 8 1287
野趣味
野趣味 2020-11-27 06:05
def isBig(x):
   if x > 4: 
       return \'apple\'
   else: 
       return \'orange\'

This works:

if isBig(y): return isBig(y)
         


        
相关标签:
8条回答
  • 2020-11-27 06:42

    The one liner doesn't work because, in Python, assignment (fruit = isBig(y)) is a statement, not an expression. In C, C++, Perl, and countless other languages it is an expression, and you can put it in an if or a while or whatever you like, but not in Python, because the creators of Python thought that this was too easily misused (or abused) to write "clever" code (like you're trying to).

    Also, your example is rather silly. isBig() will always evaluate to true, since the only string that's false is the empty string (""), so your if statement is useless in this case. I assume that's just a simplification of what you're trying to do. Just do this:

    tmp = isBig(y)
    if tmp: return tmp
    

    Is it really that much worse?

    0 讨论(0)
  • 2020-11-27 06:43

    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
    
    0 讨论(0)
  • 2020-11-27 06:48

    The problem is that the assignment operation cannot be evaluated as having a boolean value. The if statement relies on being able to evaluate a boolean. For example,

    >>> fruit = 'apple'
    >>> bool(fruit = 'apple')
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    
    /Users/jem/<ipython console> in <module>()
    
    TypeError: 'fruit' is an invalid keyword argument for this function
    >>> bool('a')
    True
    
    0 讨论(0)
  • 2020-11-27 06:53

    This doesn't work due to intentional language design, but you can use this trick to get around this decision

    0 讨论(0)
  • 2020-11-27 06:57
    print "apple" if x > 4 else "orange"
    
    0 讨论(0)
  • 2020-11-27 07:01

    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).

    0 讨论(0)
提交回复
热议问题