繁体   English   中英

从 python 函数分配可变数量的返回值的优雅方法

[英]Elegant way to assign a variable number of returns from a python function

我正在使用一个 python 库,它的函数将结果作为列表返回。 根据实验配置,此列表由一个或两个元素组成。 在这种情况下,分配函数输出的直接方法如下:

bbox, segm = None, None
results = test_model()  # returns a list with either one or two elements
bbox = results[0]
if len(results) > 1:
    segm = results[1]

# [some other code here]
if segm is not None:
    plot(segm)

然而,这似乎很冗长,因为我们需要首先将bboxsegm初始化为None ,然后评估if len(results) > 1 有什么pythonic方法可以避免这种情况吗? 理想情况下,这样的事情会非常好:

bbox, segm = test_model()  # returns a list with either one or two elements
if segm is not None:
    plot(segm)

您可以使用 Python 3.10 中提供的结构模式匹配

match test_model():
   case [bbox, segm]:
      plot(segm)
   case bbox:
      pass

但是,如果test_module总是返回一个元组,则可以使用解包:

bbox, *segm = test_model()

现在,如果text_model返回一个值, segm将是一个空列表 ( [] )。 但是,如果它返回两个值,则segm将包含单个元素。 因此,您的完整代码可以变成:

bbox, *segm = test_model()
if segm:
   plot(segm[0])

如果您使用的是 Python 3.10,请使用Ajax1234 的答案

否则,您的首要任务是写一些易于阅读的东西,而不是做任何花哨的事情。 分配给这样的元组会起作用:

try:
    bbox, segment = results
except ValueError:
    bbox, segment = results[0], None

这有很多优点:

  • 你一眼就能看出正在发生的事情。
  • 如果列表的长度不是 1 或 2,您将收到错误而不是静默失败。

在处理异常时,对实际异常的情况使用异常是有意义的。 因此,如果您希望通过一个列表项获得更多结果,您可以反过来写:

try:
    bbox, = results
    segment = None
except ValueError:
    bbox, segment = results

您可以将return list扩展为一个附加元素,然后切掉 2 个需要的元素。

def foo(boolean):
    if boolean:
        return [True, True]
    return [False]

bar, baz = (foo(False) + [None])[:2]
print(bar, baz) # False None

bar, baz = (foo(True) + [None])[:2]
print(bar, baz) # True True

pythonic 方式将是*如@Ajax1234 提到的那样解包,但这是另一种选择。

如果您可以控制函数定义,则还可以添加装饰器。

def returns_two(func):
    def wrapper(*args):
        return (func(*args) + [None])[:2]
    return wrapper


@returns_two
def foo(boolean):
    if boolean:
        return [True, True]
    return [False]


bar, baz = foo(False)
print(bar, baz) # False None

bar, baz = foo(True)
print(bar, baz) # True True

还有两种方法,如果test_model()只返回一个值, segm None分配给segm

bbox, segm, *_ = *test_model(), None
bbox, segm = (*test_model(), None)[:2]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM