【发布时间】:2010-09-26 04:11:51
【问题描述】:
以支持它的语言返回多个值的规范方法通常是tupling。
选项:使用元组
考虑这个简单的例子:
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 } 最终只是在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
__slots__声明采用一系列实例变量,并在每个实例中保留足够的空间来保存每个变量的值。因为没有为每个实例创建__dict__,所以节省了空间。
选项:使用dataclass (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 而受到污染,但混合类型列表的想法一直让我感到不舒服。在这个特定示例中,列表是 -not-mixed 类型,但可以想象它可能是。
据我所知,以这种方式使用的列表实际上对元组没有任何好处。 Python 中列表和元组之间唯一真正的区别是列表是mutable,而元组不是。
我个人倾向于继承函数式编程的约定:对任意数量的相同类型的元素使用列表,对固定数量的预定类型的元素使用元组。
问题
在冗长的序言之后,不可避免的问题来了。哪种方法(您认为)最好?
【问题讨论】:
-
在您的优秀示例中,您使用变量
y3,但除非将 y3 声明为全局变量,否则这将产生NameError: global name 'y3' is not defined,也许只使用3? -
许多带有好答案的好问题都被关闭了,因为出现了“意见”关键字。您可能会争辩说整个 SO 都是基于意见的,但它是由事实、参考资料和特定专业知识得出的意见。仅仅因为有人问“你认为哪个最好”并不意味着他们要求从现实世界的事实、参考资料和特定专业知识中抽象出来的个人意见。他们几乎可以肯定地要求正是这种意见,这种意见完全基于并记录了该人用来形成意见的事实、参考资料和具体专业知识。
-
@hetepeperfan 不需要更改 3,也不需要在全局中定义 y3,您也可以使用本地名称
y3,也可以完成相同的工作。
标签: python coding-style return return-value