关于python:函数返回多个值是合适的吗?

Is it pythonic for a function to return multiple values?

在Python中,可以让函数返回多个值。这里有一个人为的例子:

1
2
3
4
5
6
def divide(x, y):
    quotient = x/y
    remainder = x % y
    return quotient, remainder  

(q, r) = divide(22, 7)

这似乎很有用,但看起来它也可能被滥用("好吧..函数x已经计算出作为中间值所需要的东西。"让x返回该值)。

你应该什么时候画线和定义一个不同的方法?


绝对(例如您提供的示例)。

tuples是python中的头等公民

有一个内建函数divmod()可以做到这一点。

1
q, r = divmod(x, y) # ((x - x%y)/y, x%y) Invariant: div*y + mod == x

还有其他例子:zipenumeratedict.items

1
2
3
4
5
6
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库引用参考:

Tuples may be constructed in a number of ways:

  • Using a pair of parentheses to denote the empty tuple: ()
  • Using a trailing comma for a singleton tuple: a, or (a,)
  • Separating items with commas: a, b, c or (a, b, c)
  • Using the tuple() built-in: tuple() or tuple(iterable)

功能应为单一目的服务

因此,它们应该返回单个对象。在您的例子中,这个对象是一个元组。将元组视为特殊的复合数据结构。有些语言几乎每个函数都返回多个值(lisp中的列表)。

有时返回(x, y)而不是Point(x, y)就足够了。

命名元组

在Python2.6中引入命名元组后,在许多情况下,最好返回命名元组,而不是纯元组。

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> 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


首先,注意python允许以下内容(不需要括号):

1
q, r = divide(22, 7)

关于你的问题,没有硬性和快速的规则。对于简单的(通常是人为的)例子,似乎给定函数总是可能有一个单一的用途,从而产生一个单一的值。但是,在将Python用于实际应用程序时,您很快就会遇到许多情况,其中需要返回多个值,从而导致代码更干净。

所以,我想说,做任何有意义的事情,不要试图遵守一个人为的约定。python支持多个返回值,因此在适当的时候使用它。


您给出的示例实际上是一个名为divmod的python内置函数。所以有人,在某个时间点上,认为这是一个足以包含在核心功能的Python。

对我来说,如果代码更干净,那就是Python。比较这两个代码块:

1
2
3
4
5
6
7
8
9
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

是的,返回多重价值(i.e.,a tuple)是定义的Python。由于其他人已经指明,在Python标准图书馆以及在适当的Python项目中都有许多例子。另外两个评论:

  • 回报多重价值有时非常有用。举例来说,采用一种可选择地处理某一事件(在这样做时回报某些价值)的方法,同时又回报成功或失败。这可能是一个责任模式的链条。在其他情况下,你想要复制多个,封闭链接数据的一部分----例如在给出的例子中。在这一设定中,回归多值是返回一个匿名类的单个实例,其中有多个成员变量。
  • Python's handling of method determinates necessitates the ability to directly return multiple values.例如,在C++中,方法参数可以通过引用来传输,因此,可以将输出值分配给他们,再加上形式回报值。In Python,are passed"by reference"(but in the sense of Java,not C+).你不能为方法论据分配新的价值,它反射出方法范围。For example:

    1
    2
    3
    4
    5
    6
    7
    8
    // C++
    void test(int& arg)
    {
        arg = 1;
    }

    int foo = 0;
    test(foo); // foo is now 1!

    比较:

    ZZU1


  • OT:RSRE's algol68 has the curious"/EG

    1
    2
    INT quotient:=355, remainder;
    remainder := (quotient /:= 113);

    给出一个商数,3,16。

    注:Typically the value of(X/:=Y)"is discarded as quote"X"is assigned by reference,but in RSRE's case the returned value is the remainder.

    C.F.Integer算法-算法68


    返回元组很酷。还要注意新的名称在python 2.6中添加了这个选项,这可能会使您更喜欢它:http://docs.python.org/dev/library/collections.html collections.namedtuple


    当然是Python。事实上,您可以从一个函数返回多个值,这个函数是您在C语言中使用的样板文件,在C语言中,您需要为在某个地方返回的每个类型组合定义一个结构。

    但是,如果您达到了从一个函数返回疯狂值(比如10个值)的程度,那么您应该认真考虑将它们捆绑在一个类中,因为在这一点上,它会变得很难处理。


    我是新来的Python,但水管技术看起来像是我的Python。但是,我有另一个想法,也许可以提高可行性。使用一个字典允许存取到不同值的名称比位置。For example:

    1
    2
    3
    4
    5
    6
    def divide(x, y):
        return {'quotient': x/y, 'remainder':x%y }

    answer = divide(22, 7)
    print answer['quotient']
    print answer['remainder']


    对于诸如divmod这样的简单函数,可以使用元组返回多个值。如果它使代码可读,那就是Python。

    如果返回值开始变得混乱,请检查函数是否做得太多,如果做得太多,则将其拆分。如果一个大元组被当作一个对象来使用,就把它变成一个对象。另外,考虑使用命名的元组,它将是Python2.6中标准库的一部分。