2 votes

Est-ce qu'il existe du sucre syntaxique pour une fonction qui accepte un tuple?

Supposons que j'ai une fonction qui prend deux arguments et effectue un calcul sur eux :

def add(a, b):
    return a + b

Je veux appeler cette fonction via une bibliothèque de multiprocessing qui ne peut gérer que des fonctions avec un seul argument. Ainsi, je modifie la fonction pour prendre son argument sous forme d'un seul tuple :

def add2(ab):
    a, b = ab
    return a + b

Cependant, cela me semble maladroit. Les variables doivent essentiellement être définies (et documentées) deux fois. Si j'utilisais une fonction lambda, je pourrais simplement écrire ce qui suit et elle accepterait correctement le tuple :

add3 = lambda (a, b): a + b

Malheureusement, ma fonction n'est pas assez simple pour être implémentée en tant que fonction lambda. Y a-t-il une sorte de fonctionnalité de sucre syntaxique en python qui me permettrait d'écrire une fonction nommée qui accepte un tuple mais traite chaque composant de ce tuple comme un argument nommé séparé ? Mes tentatives de recherche de solutions à ce problème ont principalement donné des références à l'opérateur *args, mais cela ne s'applique pas ici car je ne contrôle pas le site où la fonction est appelée.

Voici un exemple de la façon dont la fonction est appelée. Notez qu'elle est appelée via la bibliothèque de multiprocessing donc je ne peux pas passer plus d'un argument :

import multiprocessing
pool = multiprocessing.Pool(processes=4)
for result in pool.imap_unordered(add, [(1,2),(3,4)]):
    print(result)

Les réponses pour python 2.7 ou 3.x sont les bienvenues.

4voto

wim Points 35274

Il est préférable de ne pas modifier l'interface de fonction d'origine, ce qui la rend moins Pythonique. En Python 2, écrivez une fonction enveloppe à utiliser avec multiprocessing.

def _add(args):
    return add(*args)

En Python 3, utilisez simplement Pool.starmap à la place :

>>> def add(a, b):
...     return a + b
... 
>>> p = Pool()
>>> list(p.starmap(add, [(1, 2), ('hello', ' world')]))
[3, 'hello world']

0voto

Robᵩ Points 50501

Si vous êtes inquiet de vous répéter (a et b apparaissent trop de fois), il suffit de donner un nom non descriptif au tuple entrant.

def add(t):
    a, b = t
    return a + b

Ou, dans votre cas spécifique, vous pouvez éviter complètement a et b en indexant le tuple :

def add(addends):
    return addends[0] + addends[1]

En alternative, vous pourriez envelopper votre fonction pour que le code source ait le format d'argument familier, mais la fonction en cours d'utilisation ait l'argument de tuple :

def tupleize(func):
    def wrapper(tup):
        return func(*tup)
    return wrapper

@tupleize
def add(a, b):
    return a+b

t = 1, 2
assert(add(t) == 3)

-1voto

Flight Odyssey Points 889

Alors que j'étais en train d'écrire cette question, j'ai trouvé le moyen de le faire en Python 2.7 :

def add4((a, b)):
    return a + b

Cependant, apparemment cela ne fonctionne plus en Python 3, donc des réponses supplémentaires concernant Python 3 seraient toujours utiles.

-1voto

match Points 2574

Vous pourriez utiliser un décorateur pour étendre la fonction de la bibliothèque multiprocessing afin de prendre plusieurs arguments, de faire ce que vous voulez avec eux, puis de l'appeler avec un seul argument.

Par exemple, un décorateur simple qui prend un nombre quelconque d'arguments, les additionne, puis appelle la fonction d'origine avec le total en tant qu'argument unique :

import 3rdpartylib

def sum_args(func):
    def inner(*args):
      return func(sum(args))
    return inner

# Remplacer la fonction importée par la version décorée
3rdpartylib = sum_args(3rdpartylib)

# Décorer vos propres bibliothèques
@sum_args
def my_own_lib(number):
    print("A:", number)

3rdpartylib(1,2,3,4)
my_own_lib(5,10,15)

Le principal avantage est que vous pouvez décorer/remplacer un nombre quelconque de méthodes avec cette même fonction de décorateur pour obtenir le même effet.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X