Python函数中返回值的数量不同

Different number of return values in Python function

从Python中的函数返回不同数量的返回值是否可以/良好的做法?如果是,调用方应该如何处理返回值?例如

1
2
3
4
5
6
7
def func():
    if(condition_1):
        return 1,2
    if(condition_2):
        return 1
    if(condition_3):
        return 1,2,3,4

注:条件1、条件2和条件3是函数func的局部条件,因此调用方不知道将返回多少值。


可以返回多个值,但您必须将所有返回的值保持为相同的形式/类型,以便使用:

1
2
3
4
5
6
7
def func():
    if(condition_1):
        return 1, 2
    if(condition_2):
        return 1,    # return a tuple same as the others
    if(condition_3):
        return 1, 2, 3, 4

函数是否返回多个值?对此有一个很好的解释。

但在您的案例中,这取决于您的用例。如果您知道如何处理返回的数据,那么使用它没有问题。像:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def func():
    if(condition_1):
        return a,b
    if(condition_2):
        return (a, )
    if(condition_3):
        return c,d,e,f
    if(condition_4):
        return a,b

vals = func()
if len(vals) == 2:
    # We are sure that we will get `a,b` in return
    do something ...
elif len(vals) == 3:
    ...

在上面的例子中,处理vals元组的函数知道如何根据某些条件处理返回的数据。它有2个返回相同数据的return可能性!

如果您确切知道如何处理数据,那么可以使用不同数量的返回。这里的关键点是函数执行单个任务。如果您在识别返回值时遇到问题,那么您的函数将执行多个作业,或者必须避免使用不同数量的参数。


我会避免的。一般来说(尽管偶尔会有例外),正如其他人提到的,从函数的每个分支返回相同类型的对象是一个好主意。然而,这不仅仅是在一个元素元组中包装单一的返回值——考虑一种模式,即返回相同数量的东西(以相同的顺序),并对任何不适用于该分支的东西使用None或某种特定类型的"空"值(空对象模式)。

这意味着客户端代码总是可以做到这一点:

1
a, b, c, d, e = func()

忽略它不关心的任何价值观。如果混合使用空对象模式,那么即使关心可能不存在的值的代码也不必对它们进行特殊的区分。如果您改变了元组的长度,那么每个调用都必须为任何分支的结果做好准备,这意味着它几乎必须匹配您的分支。

对于您和调用代码来说,执行这种模式的一个非常好的方法是使用collections.namedtuple。这也有一个很好的好处,使您的代码立即更自我记录。


虽然这是主观的,但我喜欢返回字典-这有助于避免考虑返回的顺序,我可以部分返回(例如,5个元素中有3个元素),它使代码更具可读性。

1
2
3
4
5
6
7
8
9
def func():
    if(condition_1):
        return {'name': 'Joe', 'age': 32}
    if(condition_2):
        return {'name': 'Mary'}

res = func()
name = res.get('name', 'unknown')
age = res.get('age', 0)