用支持它的语言返回多个值的规范方法通常是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
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.
使用Python3.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中,列表和元组之间唯一真正的区别是列表是mutable,而元组不是。
我个人倾向于继承函数式编程的惯例:对于同一类型的任意数量的元素使用列表,对于预定类型的固定数量的元素使用元组。
我通常发现自己走字典的路线,因为它涉及较少的设置工作。然而,从类型的角度来看,您最好走类路径,因为这可以帮助您避免混淆字典所表示的内容。
另一方面,Python社区中有一些人觉得implied interfaces should be preferred to explicit interfaces,此时对象的类型实际上并不相关,因为您基本上依赖于相同属性始终具有相同含义的约定。
那么,如何在Python中返回多个值呢?
很多答案都表明你需要返回某种类型的集合,比如字典或列表。您可以省略额外的语法,只需写出以逗号分隔的返回值。注意:这在技术上返回一个元组。
给出:
为此,在2.6中添加了Named tuples。有关类似的内置示例,请参见os.stat。
在Python 3的最新版本(我认为是3.6+)中,新的} 类,使命名元组更易于创建,功能更强大。继承自
typing
库获得了^{typing.NamedTuple
允许您使用docstring、默认值和类型注释。示例(来自文档):
对于小项目,我发现使用元组最容易。当这变得太难管理(而不是以前)时,我开始将事情分组为逻辑结构,但是我认为您建议的使用字典和
ReturnValue
对象是错误的(或过于简单化)。返回键为
"y0"
、"y1"
、"y2"
等的字典与元组相比没有任何优势。与元组相比,返回具有属性.y0
、.y1
、.y2
等的ReturnValue
实例也没有任何优势。如果你想得到任何东西,你需要开始命名,而且你可以使用元组来完成:IMHO,除了元组之外,唯一好的技术就是用正确的方法和属性返回真实的对象,就像从
re.match()
或open(file)
获得的那样。相关问题 更多 >
编程相关推荐