如何从一个函数返回多个值? [英] How do I return multiple values from a function?

查看:91
本文介绍了如何从一个函数返回多个值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

The canonical way to return multiple values in languages that support it is often tupling.

请考虑以下简单示例:

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

但是,随着返回的值增加。如果要返回四个或五个值怎么办?当然,您可以继续修改它们,但是很容易忘记哪个值在哪里。

However, this quickly gets problematic as the number of values returned increases. What if you want to return four or five values? Sure, you could keep tupling them, but it gets easy to forget which value is where. It's also rather ugly to unpack them wherever you want to receive them.

下一个合理的步骤似乎是引入某种记录符号。在Python中,显而易见的方法是通过 dict

The next logical step seems to be to introduce some sort of 'record notation'. In Python, the obvious way to do this is by means of a dict.

请考虑以下内容:

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

(显然,y0,y1和y2只是抽象标识符。正如指出的那样,在实践中,您将使用有意义的标识符。)

(Just to be clear, y0, y1, and y2 are just meant as abstract identifiers. As pointed out, in practice you'd use meaningful identifiers.)

现在,我们有了一种机制,我们可以投影出返回对象的特定成员。例如,

Now, we have a mechanism whereby we can project out a particular member of the returned object. For example,

result['y0']


选项:使用类


但是,还有另一个选择。相反,我们可以返回一个专门的结构。我已经在Python上下文中对此进行了框架化,但是我确定它也适用于其他语言。确实,如果您使用C语言,这很可能是您唯一的选择。

Option: Using a class

However, there is another option. We could instead return a specialized structure. I've framed this in the context of Python, but I'm sure it applies to other languages as well. Indeed, if you were working in C this might very well be your only option. Here goes:

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)

In Python的前两个在管道方面可能非常相似-毕竟 {y0,y1,y2} 最终只是内部 __ dict__的条目

In Python the previous two are perhaps very similar in terms of plumbing - after all { y0, y1, y2 } just end up being entries in the internal __dict__ of the ReturnValue.

ReturnValue 中的。Python为微小对象提供了另一项功能, __ slots __ 属性。该类可以表示为:

There is one additional feature provided by Python though for tiny objects, the __slots__ attribute. The class could be expressed as:

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

来自 Python参考手册


__ slots __ 声明接受一系列实例变量,并在每个实例中仅保留足够的空间来容纳每个变量的值。因为未为每个实例创建 __ dict __ ,所以节省了空间。

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.


选项:使用数据类(Python 3.7 +)


使用Python 3.7的新数据类返回具有自动添加的特殊方法,类型和其他有用工具的类:

Option: Using a dataclass (Python 3.7+)

Using Python 3.7's new dataclasses, return a class with automatically added special methods, typing and other useful tools:

@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)


选项:使用列表


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

Option: Using a list

Another suggestion which I'd overlooked comes from Bill the Lizard:

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

这是我最不喜欢的方法。我想我对接触Haskell感到很受污染,但是混合类型列表的想法一直让我感到不舒服。在此特定示例中,列表是-no-混合类型,但可以想象是这样。

This is my least favorite method though. I suppose I'm tainted by exposure to Haskell, but the idea of mixed-type lists has always felt uncomfortable to me. In this particular example the list is -not- mixed type, but it conceivably could be.

以这种方式使用的列表实际上在元组方面并没有任何好处我可以告诉。 Python中列表和元组之间的唯一真正区别是列表是可变

A list used in this way really doesn't gain anything with respect to the tuple as far as I can tell. The only real difference between lists and tuples in Python is that lists are mutable, whereas tuples are not.

我个人倾向于继承函数式编程中的约定:对任何数量的相同类型的元素使用列表,对元组的固定数量的元素使用元组

I personally tend to carry over the conventions from functional programming: use lists for any number of elements of the same type, and tuples for a fixed number of elements of predetermined types.

在冗长的序言之后,出现了不可避免的问题。

After the lengthy preamble, comes the inevitable question. Which method (do you think) is best?

推荐答案

命名元组。有关类似的内置示例,另请参见 os.stat

Named tuples were added in 2.6 for this purpose. Also see os.stat for a similar builtin example.

>>> import collections
>>> Point = collections.namedtuple('Point', ['x', 'y'])
>>> p = Point(1, y=2)
>>> p.x, p.y
1 2
>>> p[0], p[1]
1 2

最新版本的Python 3 (我认为是3.6+),新的 typing 库获得了 NamedTuple 类使命名元组更易于创建且功能更强大。从 typing.NamedTuple 继承,您可以使用文档字符串,默认值和类型注释。

In recent versions of Python 3 (3.6+, I think), the new typing library got the NamedTuple class to make named tuples easier to create and more powerful. Inheriting from typing.NamedTuple lets you use docstrings, default values, and type annotations.

示例(来自docs ):

Example (From the docs):

class Employee(NamedTuple):  # inherit from typing.NamedTuple
    name: str
    id: int = 3  # default value

employee = Employee('Guido')
assert employee.id == 3

这篇关于如何从一个函数返回多个值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆