获取Python函数以干净地返回标量或列表,具体取决于参数的数量

Nev*_*vir 5 python python-2.x python-2.6 iterable-unpacking

免责声明:我正在寻找一个Python 2.6解决方案,如果有的话.

我正在寻找一个函数,当传递单个值时返回单个值,或者在传递多个值时返回一个序列:

>>> a = foo(1)
2
>>> b, c = foo(2, 5)
>>> b
3
>>> c
6
Run Code Online (Sandbox Code Playgroud)

要清楚,这是为了使一些函数调用看起来比以下更好:

a, = foo(1)
Run Code Online (Sandbox Code Playgroud)

要么

a = foo(1)[0]
Run Code Online (Sandbox Code Playgroud)

现在,不优雅的解决方案是这样的:

def foo(*args):
    results = [a + 1 for a in args]
    return results if len(results) > 1 else results[0]
Run Code Online (Sandbox Code Playgroud)

是否有任何语法糖(或功能)会让这感觉更清洁?以下任何事情?

def foo(*args):
    return *[a + 1 for a in args]
Run Code Online (Sandbox Code Playgroud)

Mik*_*iak 7

你总是可以编写一个装饰器来删除if语句,如果这对你更好:

import functools
def unpacked(method):
    @functools.wraps(method)
    def _decorator(*args):
        result = method(*args)
        return results if len(results) != 1 else results[0]
    return _decorator
Run Code Online (Sandbox Code Playgroud)

用法:

@unpacked
def foo(*args):
    return [arg + 1 for arg in args]
Run Code Online (Sandbox Code Playgroud)


kin*_*all 6

scalify如果列表只有一个元素,你可以很容易地编写一个从列表中返回元素的函数,即它试图使它成为标量(因此得名).

def scalify(l):
    return l if len(l) > 1 else l[0]
Run Code Online (Sandbox Code Playgroud)

然后你可以在你的函数中使用它,如下所示:

def foo(*args):
    return scalify([a + 1 for a in args])
Run Code Online (Sandbox Code Playgroud)

这样做可以解决问题,但我和那些暗示你不这样做的人在一起.出于一个原因,除非您知道至少传递了两个项目,否则它会排除迭代结果.此外,如果您有一个列表,则必须在调用该函数时解压缩列表,丢失其"listness",并且您知道可能无法获得列表.在我看来,这些缺点掩盖了您对该技术可能看到的任何好处.