简体   繁体   English

当期望多个返回值时,如何从函数中很好地返回

[英]How to return from function nicely when multiple return values expected

The myFunct is expected to return two values. myFunct应该返回两个值。 Both returned values are captured to var_1, var_2 . 两个返回的值都捕获到var_1, var_2

As an error check I am using a lot of if/else: return statement inside of scope of the function called ( myFunct in this case). 作为错误检查,我在被调用的函数范围内使用了if/else: return语句(在本例中为myFunct )。 Typing simple if arg<10: return returns a single None which raises TypeError: 'NoneType' object is not iterable since there are two variables: var_1, var_2 = myFunct(5) expecting two returned values but only a single value None is returned. if arg<10: return键入简单, if arg<10: return返回单个 None ,引发TypeError: 'NoneType' object is not iterable因为有两个变量: var_1, var_2 = myFunct(5)期望两个返回值,但仅返回单个值None

In order to avoid an error like this I would have to use a following syntax: 为了避免出现这样的错误,我必须使用以下语法:

if arg<10: return None, None

which I find pretty ugly. 我觉得这很丑。

I wonder if there is a nicer way to do it... 我想知道是否有更好的方法...

def myFunct(arg):
    if arg<10:
        return
    return 100, 200

var_1, var_2 = myFunct(5)

If something is broken, the correct solution is to raise an exception. 如果发生故障,正确的解决方案是引发异常。 However, if you definitely don't want to do this, you could always: 但是,如果您绝对不想这样做,则可以始终:

try:
    var_1, var_2 = myFunct(5)
except TypeError:
    var_1, var_2 = (None,None)

Edit: 编辑:

Perhaps you need to think about what you are going to do with your var_1 and var_2 if they are indeed None. 如果var_1var_2确实为None,则可能需要考虑如何var_2它们。 If you are going to continue a calculation for which None is a valid input, then probably return None,None is the correct expression. 如果要继续进行计算,无输入是有效输入,则可能return None,None是正确的表达式。 If, however, this is an exception, and you are going to note that the result is None, and do something completely different (which does not have two values), then you can always do this: 但是,如果这是一个例外,并且您将注意到结果为“无”,并且执行完全不同的操作(没有两个值),则始终可以执行以下操作:

result = myFunct(5)
if result:
    var_1,var_2=result
    do_more_stuff_here_with(var_1 and var_2) # logical and :)
else:
    print "myFunct(5) failed - check (and if necessary adjust) the phase of the moon"

While this is debatable, it's usually considered good practice to have a single point of exit . 尽管这值得商bat,但通常认为只有一个出口即可 In other words, only one return statement. 换句话说,只有一个return语句。 You can accomplish this as follows, 您可以按以下步骤完成此操作,

def myFunc(arg):
    result1, result2 = None, None
    if not arg < 10:
        result1, result2 = 100,200
    return result1, result2

Now obviously, your toy example is so simple there are even more pythonic ways you can simplify this specific example, such as: 现在显然,您的玩具示例非常简单,甚至可以使用更多的python方式简化此特定示例,例如:

def myFunc(arg):
    return (None, None) if arg < 10 else (100,200)

But the single point of exit is a good practice to get into for my complex functions. 但是, 单点退出是进入我的复杂功能的一个好习惯。

And as others have pointed out, raising exceptions is the most pythonic way to signal that a function reached an error condition. 正如其他人指出的那样,引发异常是表示函数达到错误状态的最Python方式。 None as a return should generally only be used to signal essentially the equivalent of an empty list, IE where getting nothing back is an expected possible outcome of the function. 作为返回值的None返回值通常仅应基本上表示一个空列表的等效项,即IE,其中无返回值是该功能的预期可能结果。

How about a lovely decorator? 可爱的装饰师怎么样?

import decorator

def default_return_value(value):
    @decorator.decorator
    def decorate(f, *args, **kwargs):
        x = f(*args, **kwargs)
        return value if x is None else x
    return decorate

def returns_tuple(size):
    return default_return_value(tuple([None] * size))

@returns_tuple(size=2)
def myFunct(arg):
    if arg >= 10:
        return 100, 200

>>> myFunct(15)
(100, 200)

>>> myFunct(5)
(None, None)

Store the result in a single variable then expand it as needed 将结果存储在单个变量中,然后根据需要扩展

result = myFunct(5)
var_1, var_2 = (None, None) if result is None else result

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

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