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

时间:2010-10-27 00:02:26

标签: python python-2.6 python-2.x iterable-unpacking

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

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

>>> a = foo(1)
2
>>> b, c = foo(2, 5)
>>> b
3
>>> c
6

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

a, = foo(1)

a = foo(1)[0]

现在,不合理的解决方案就是这样:

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

是否有任何语法糖(或功能)可以使这感觉更干净?以下是什么?

def foo(*args):
    return *[a + 1 for a in args]

5 个答案:

答案 0 :(得分:6)

你总是可以写一个装饰器,如果你对这个语句更好的话就会忽略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

用法:

@unpacked
def foo(*args):
    return [arg + 1 for arg in args]

答案 1 :(得分:6)

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

def scalify(l):
    return l if len(l) > 1 else l[0]

然后你可以在你的函数中使用它:

def foo(*args):
    return scalify([a + 1 for a in args])

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

答案 2 :(得分:1)

你的意思是你想要一个具有相同数量参数的元组吗?这不是解决方案吗?

return tuple([a + 1 for a in args])

答案 3 :(得分:0)

def foo(*args):
    return (None, args[0]+1 if args else None, map(lambda a: a + 1, args))[len(args) if len(args) < 3 else 2]

:-)这是地狱

答案 4 :(得分:0)

这将处理0个或更多args,我认为这就是你要找的东西。

def foo(*args):
    return map(lambda x: x + 1, args) or [None]

编辑:我修改了添加无名单,包括解压0参数