在支持它的语言中返回多个值的规范方法通常是

tupling。

选项:使用元组

考虑这个琐碎的例子:

def f(x):
y0 = x + 1
y1 = x * 3
y2 = y0 ** y3
return (y0,y1,y2)

但是,随着返回值的数量增加,这很快就会出现问题。如果要返回四个或五个值,该怎么办?当然,你可以保持tupling他们,但它很容易忘记哪个值是哪里。这也是相当丑陋,打开他们,无论你想接收他们。

选项:使用字典

下一个逻辑步骤似乎是引入某种“记录符号”。在python中,明显的方法是通过一个dict。

考虑以下:

def g(x):
y0 = x + 1
y1 = x * 3
y2 = y0 ** y3
return {'y0':y0, 'y1':y1 ,'y2':y2 }

(编辑 – 只是为了清楚,y0,y1和y2只是作为抽象的标识符。正如所指出的,在实践中,你会使用有意义的标识符)

现在,我们有一个机制,我们可以计算出一个返回的对象的特定成员。例如,

result['y0']

选项:使用类

但是,还有另一个选择。我们可以返回一个专门的结构。我已经在Python的上下文框架,但我确信它也适用于其他语言。事实上,如果你在C工作,这可能是你唯一的选择。开始:

class ReturnValue(object):
def __init__(self, y0, y1, y2):
self.y0 = y0
self.y1 = y1
self.y2 = y2
def g(x):
y0 = x + 1
y1 = x * 3
y2 = y0 ** y3
return ReturnValue(y0, y1, y2)

在python中,前两个可能在管道方面非常相似 – 毕竟{y0,y1,y2}刚刚结束是ReturnValue的内部__dict__中的条目。

Python还提供了一个额外的功能,对于微小的对象,__slots__属性。类可以表示为:

class ReturnValue(object):
__slots__ = ["y0", "y1", "y2"]
def __init__(self, y0, y1, y2):
self.y0 = y0
self.y1 = y1
self.y2 = y2

The __slots__ declaration takes a sequence of instance variables and reserves just enough space in each instance to hold a value for each variable. Space is saved because __dict__ is not created for each instance.

选项:使用列表

我忽略的另一个建议来自比尔蜥蜴:

def h(x):
result = [x + 1]
result.append(x * 3)
result.append(y0 ** y3)
return result

这是我最不喜欢的方法。我想我受到暴露在Haskell的污染,但混合类型列表的想法一直对我感到不舒服。在该特定示例中,列表是非混合类型,但是可以想到可以是。以这种方式使用的列表对于元组来说实际上没有获得任何东西,只要我能告诉。 Python中的列表和元组之间唯一的区别是列表是mutable,wheras元组不是。我个人倾向于继承来自函数式编程的约定:使用相同类型的任何数量的元素的列表,以及用于固定数量的预定类型的元素的元组。

题:

在冗长的序言之后,出现了不可避免的问题。哪种方法(你认为)是最好的?

我通常发现自己去字典路由,因为它涉及更少的设置工作。然而,从类型的角度来看,你可能更好地去类路由,因为这可以帮助你避免混淆字典表示什么。另一方面,在Python社区有一些感觉implied interfaces should be preferred to explicit interfaces,在这一点对象的类型真的是不相关的,因为你基本上依赖于相同的属性将永远具有相同的意义的约定。