如何在IF条件中赋值并返回变量?
def isBig(x):
if x > 4:
return 'apple'
else:
return 'orange'
这个可以用:
if isBig(y): return isBig(y)
这个不行:
if fruit = isBig(y): return fruit
为什么第二个不行呢!?我想要一行代码。不过,第一个会调用这个函数两次。
怎么才能让它变成一行代码,而且不调用两次这个函数呢?
6 个回答
这段代码之所以不能工作,是因为在Python中,赋值(比如 fruit = isBig(y)
)是一个语句,而不是一个表达式。在C、C++、Perl等很多其他编程语言中,赋值是可以作为表达式使用的,你可以把它放在 if
或 while
里,随便怎么用都可以,但在Python中不行,因为Python的设计者认为这样容易被滥用,写出一些“聪明”的代码(就像你现在想做的那样)。
另外,你的例子有点搞笑。isBig()
函数总是会返回 true
,因为在Python中,只有空字符串(""
)是假的,所以在这种情况下你的 if
语句是没用的。我猜这只是你想做的事情的一个简化版本。你可以这样做:
tmp = isBig(y)
if tmp: return tmp
这真的有那么糟糕吗?
从 Python 3.8
开始,引入了 赋值表达式 (PEP 572),也就是 :=
这个符号。现在你可以把条件的值(比如 isBig(y)
)存储到一个变量(比如 x
)里,这样在条件的主体部分就可以重复使用这个值了:
if x := isBig(y): return x
我看到有人提到了我之前的“赋值和设置”食谱,简单来说就是:
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和一些直接支持在if
或while
中赋值的语言之间的转换更简单。如果你有“成百上千”这样的检查和返回的情况,完全换个做法会好得多:
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等语言。