函数返回多个值是否符合Python风格?
在Python中,你可以让一个函数返回多个值。下面是一个简单的例子:
def divide(x, y):
quotient = x/y
remainder = x % y
return quotient, remainder
(q, r) = divide(22, 7)
这看起来很有用,但也可能被滥用(比如“嗯……函数X已经计算了我们需要的中间值。那就让X也返回这个值吧”)。
那么,什么时候你应该划定界限,定义一个不同的方法呢?
9 个回答
13
你给出的例子其实是Python自带的一个函数,叫做divmod
。所以在某个时候,有人觉得这个函数足够符合Python的风格,所以把它放进了Python的核心功能里。
在我看来,如果能让代码看起来更简洁,那就是符合Python风格的。来看看这两个代码块的对比:
seconds = 1234
minutes, seconds = divmod(seconds, 60)
hours, minutes = divmod(minutes, 60)
seconds = 1234
minutes = seconds / 60
seconds = seconds % 60
hours = minutes / 60
minutes = minutes % 60
27
首先,注意Python允许这样写(不需要括号):
q, r = divide(22, 7)
关于你的问题,其实没有硬性规定。对于一些简单(通常是人为设计的)例子,可能看起来每个函数总是能有一个单一的目的,返回一个值。然而,当你在实际应用中使用Python时,你会发现很多情况下需要返回多个值,这样代码会更简洁。
所以,我的建议是,做你觉得合理的事情,不要去强迫自己遵循一些不必要的规则。Python支持返回多个值,所以在合适的时候就用它。
115
当然可以(针对你提供的例子)。
元组在Python中是重要的
Python有一个内置的函数 divmod()
,它正好可以做到这一点。
q, r = divmod(x, y) # ((x - x%y)/y, x%y) Invariant: div*y + mod == x
还有其他的例子,比如 zip
、enumerate
和 dict.items
。
for i, e in enumerate([1, 3, 3]):
print "index=%d, element=%s" % (i, e)
# reverse keys and values in a dictionary
d = dict((v, k) for k, v in adict.items()) # or
d = dict(zip(adict.values(), adict.keys()))
顺便说一下,大多数情况下,括号并不是必需的。
引用自 Python库参考:元组可以通过多种方式构造:
- 使用一对括号表示空元组: ()
- 使用尾随逗号表示单元素元组: a,或者 (a,)
- 用逗号分隔多个元素: a,b,c 或 (a,b,c)
- 使用内置的 tuple() 函数: tuple() 或 tuple(iterable)
函数应该有单一的目的
因此,它们应该返回一个单一的对象。在你的例子中,这个对象就是一个元组。可以把元组看作是一种临时的复合数据结构。在某些编程语言中,几乎每个函数都会返回多个值(比如Lisp中的列表)。
有时候,返回 (x, y)
就足够了,而不是 Point(x, y)
。
命名元组
自从Python 2.6引入命名元组后,在很多情况下,返回命名元组比返回普通元组更好。
>>> import collections
>>> Point = collections.namedtuple('Point', 'x y')
>>> x, y = Point(0, 1)
>>> p = Point(x, y)
>>> x, y, p
(0, 1, Point(x=0, y=1))
>>> p.x, p.y, p[0], p[1]
(0, 1, 0, 1)
>>> for i in p:
... print(i)
...
0
1