![](/img/trans.png)
[英]Python - safe & elegant way to set a variable from function that may return None
[英]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)
然而,这似乎很冗长,因为我们需要首先将bbox
和segm
初始化为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
这有很多优点:
在处理异常时,对实际异常的情况使用异常是有意义的。 因此,如果您希望通过一个列表项获得更多结果,您可以反过来写:
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.