用支持它的语言返回多个值的规范方法通常是麻烦的。
选项:使用元组
考虑下面这个简单的例子:
def f(x):
y0 = x + 1
y1 = x * 3
y2 = y0 ** y3
return (y0, y1, y2)
但是,随着返回值的数量增加,这很快就会成为问题。如果要返回四个或五个值怎么办?当然,您可以继续修改它们,但是很容易忘记哪个值在哪里。在任何要接收它们的地方打开它们的包装也是很丑陋的。
选项:使用字典
下一步的逻辑步骤似乎是引入某种“记录符号”。在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:
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 }
最终只是__dict__
在ReturnValue
。
Python提供了一项附加功能,尽管对于微小的对象,__slots__
属性。该类可以表示为:
class ReturnValue(object):
__slots__ = ["y0", "y1", "y2"]
def __init__(self, y0, y1, y2):
self.y0 = y0
self.y1 = y1
self.y2 = y2
该
__slots__
声明采用一系列实例变量,并在每个实例中仅保留足够的空间来容纳每个变量的值。因为__dict__
未为每个实例创建空间,所以节省了空间。
选项:使用数据类(Python 3.7+)
使用Python 3.7的新数据类,返回一个具有自动添加的特殊方法,键入和其他有用工具的类:
@dataclass
class Returnvalue:
y0: int
y1: float
y3: int
def total_cost(x):
y0 = x + 1
y1 = x * 3
y2 = y0 ** y3
return ReturnValue(y0, y1, y2)
选项:使用列表
我忽略的另一个建议来自蜥蜴人比尔:
def h(x):
result = [x + 1]
result.append(x * 3)
result.append(y0 ** y3)
return result
这是我最不喜欢的方法。我想我对接触Haskell感到很受污染,但是混合类型列表的想法一直让我感到不舒服。在此特定示例中,列表为“非混合”类型,但可以想象是这样。
据我所知,以这种方式使用的列表实际上对元组没有任何好处。Python中列表和元组之间的唯一真正区别是列表是可变的,而元组则不是。
我个人倾向于继承函数式编程的约定:对任何数量的相同类型的元素使用列表,对固定数量的预定类型的元素使用元组。
题
在冗长的序言之后,出现了不可避免的问题。(您认为)哪种方法最好?
y3
,它也可以完成相同的工作。
y3
,但是除非将y3声明为全局变量,否则NameError: global name 'y3' is not defined
可能只使用3
?