在支持它的语言中返回多个值的规范方法通常是
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,在这一点对象的类型真的是不相关的,因为你基本上依赖于相同的属性将永远具有相同的意义的约定。
那么,如何 – 在Python中返回多个值?