从函数返回多个值的最佳方法? [英] Best way to return multiple values from a function?

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

问题描述

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

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)

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

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.

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)

选项:使用列表

蜥蜴人比尔(Bill the Lizard)是我忽略的另一个建议:

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而受污染,但是混合类型列表的想法一直让我感到不舒服.在此特定示例中,列表是-not-混合类型,但可以想象是.

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 库获得了

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.

示例(来自文档):

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

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

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

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