Obtenir une fonction Python pour revenir proprement un scalaire ou d'une liste, en fonction du nombre d'arguments

StackOverflow https://stackoverflow.com/questions/4029001

Question

Disclaimer:. Je suis à la recherche d'une solution Python 2.6, s'il y a un

Je recherche une fonction qui renvoie une valeur unique lorsqu'il est passé une valeur unique, ou qui renvoie une séquence lorsqu'il est passé plusieurs valeurs:

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

Pour être clair, cela est dans le but de faire des appels de fonction il suffit de regarder plus agréable que:

a, = foo(1)

ou

a = foo(1)[0]

En ce moment, la solution inélégante est quelque chose le long de ces lignes:

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

Y at-il du sucre syntaxique (ou fonctions) qui rendrait cette sensation plus propre? quelque chose comme ce qui suit?

def foo(*args):
    return *[a + 1 for a in args]
Était-ce utile?

La solution

Vous pouvez facilement écrire un scalify de fonction qui renvoie l'élément de la liste si la liste ne comporte qu'un seul élément, à savoir qu'il essaie d'en faire un scalaire (d'où le nom).

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

Ensuite, vous pouvez l'utiliser dans vos fonctions comme ceci:

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

fera l'affaire, mais je suis avec ceux qui vous suggère de ne pas le faire. Pour une raison, elle exclut itérer sur le résultat à moins que vous savez que vous avez passé dans au moins deux éléments. En outre, si vous avez une liste, vous devez décompresser la liste lors de l'appel de la fonction, perdant son « listness », et vous savez que vous ne pouvez pas obtenir une liste de retour. Ces inconvénients me semblent éclipser tout avantage que vous pouvez voir à la technique.

Autres conseils

Vous pouvez toujours écrire un décorateur à elide que si la déclaration si cela est plus agréable pour vous:

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

Utilisation:

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

Voulez-vous dire que vous voulez un tuple avec le même nombre d'arguments? Est-ce pas une solution?

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]

:-) il est l'enfer

se chargera 0 ou plus args, je pense que ce que vous recherchez.

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

modifier: Je révisé pour ajouter une liste Aucun Incase de déballage 0 args

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top