Obtención de una función de Python para devolver limpiamente un escalar o una lista, según el número de argumentos

Descargo de responsabilidad: estoy buscando una solución de Python 2.6, si la hay.

Estoy buscando una función que devuelve un solo valor cuando se pasa un solo valor, o que devuelve una secuencia cuando se pasan varios valores:

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

Para que quede claro, esto es un esfuerzo por hacer que algunas llamadas a funciones simplemente se vean mejor que:

 a, = foo(1) 

o

 a = foo(1)[0] 

En este momento, la solución poco elegante es algo como esto:

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

¿Hay algún azúcar sintáctico (o funciones) que lo haga sentir más limpio? Algo como lo siguiente?

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

Puede escribir fácilmente una función de scalify que devuelva el elemento de la lista si la lista tiene solo un elemento, es decir, trata de convertirlo en un escalar (de ahí el nombre).

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

Entonces puedes usarlo en tus funciones así:

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

Esto hará el truco, pero estoy con aquellos que sugieren que no lo hagas. Por una razón, descarta iterar sobre el resultado a menos que sepa que pasó al menos dos elementos. Además, si tiene una lista, debe descomprimir la lista al llamar a la función, perder su “listness” y sabe que es posible que no vuelva a recibir una lista. Me parece que estos inconvenientes eclipsan cualquier beneficio que pueda tener la técnica.

Siempre puedes escribir un decorador para evitar esa afirmación si eso te parece mejor:

 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 

Uso:

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

¿Quieres decir que quieres una tupla con el mismo número de argumentos? ¿No es esto una solución?

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

 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] 

🙂 es el infierno

Esto manejará 0 o más argumentos, creo que eso es lo que estás buscando.

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

edición: revisé para agregar una lista Ninguno en caso de desempaquetar 0 argumentos