如何在IF条件中赋值并返回变量?

51 投票
6 回答
131648 浏览
提问于 2025-04-15 14:59
def isBig(x):
   if x > 4: 
       return 'apple'
   else: 
       return 'orange'

这个可以用:

if isBig(y): return isBig(y)

这个不行:

if fruit = isBig(y): return fruit

为什么第二个不行呢!?我想要一行代码。不过,第一个会调用这个函数两次。

怎么才能让它变成一行代码,而且不调用两次这个函数呢?

6 个回答

9

这段代码之所以不能工作,是因为在Python中,赋值(比如 fruit = isBig(y))是一个语句,而不是一个表达式。在C、C++、Perl等很多其他编程语言中,赋值是可以作为表达式使用的,你可以把它放在 ifwhile 里,随便怎么用都可以,但在Python中不行,因为Python的设计者认为这样容易被滥用,写出一些“聪明”的代码(就像你现在想做的那样)。

另外,你的例子有点搞笑。isBig() 函数总是会返回 true,因为在Python中,只有空字符串("")是假的,所以在这种情况下你的 if 语句是没用的。我猜这只是你想做的事情的一个简化版本。你可以这样做:

tmp = isBig(y)
if tmp: return tmp

这真的有那么糟糕吗?

174

Python 3.8 开始,引入了 赋值表达式 (PEP 572),也就是 := 这个符号。现在你可以把条件的值(比如 isBig(y))存储到一个变量(比如 x)里,这样在条件的主体部分就可以重复使用这个值了:

if x := isBig(y): return x
23

我看到有人提到了我之前的“赋值和设置”食谱,简单来说就是:

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

不过,这个主要是为了让Python和一些直接支持在ifwhile中赋值的语言之间的转换更简单。如果你有“成百上千”这样的检查和返回的情况,完全换个做法会好得多:

hundreds = isBig, isSmall, isJuicy, isBlah, ...

for predicate in hundreds:
  result = predicate(y)
  if result: return result

或者甚至可以这样做:

return next(x for x in (f(y) for f in hundreds) if x)

如果在没有满足条件的情况下,出现StopIteration异常是可以接受的,或者

return next((x for x in (f(y) for f in hundreds) if x)), None)

如果在没有满足条件的情况下,None是合适的返回值,等等。

几乎总是,使用(或者甚至想要使用)Holder这个技巧/非惯用法都是一种“设计异味”,这意味着你应该寻找一种不同且更符合Python风格的方法——唯一一个可以使用Holder的情况正是我设计它的特殊情况,也就是当你想要让Python代码和某个非Python代码保持紧密对应时,比如你在Python中转写一个参考算法,想先让它工作,然后再改成更符合Python风格的形式,或者你在写Python作为一个原型,等它有效后再转写成C++、C#、Java等语言。

撰写回答