2009-07-07 8 views
1

Exemple:Manière élégante d'abstraire des appels de fonction multiples?

>>> def write_to_terminal(fmt, *args): 
...  print fmt % args 
>>> LOG = logging.getLogger(__name__) 
>>> info = multicall(write_to_terminal, LOG.info) 
>>> debug = multicall(write_debug_to_terminal, LOG.debug) 
>>> ... 
>>> info('Hello %s', 'guido') # display in terminal *and* log the message 

Y at-il une façon élégante d'écrire multicall? Peut-être avec l'aide de la bibliothèque standard .. sans réinventer la roue?

+0

Pourquoi je fais cela? Parce que j'ai écrit un module séparé (appelez-le 'ui.py') qui écrit sur la console .. et utilise également la journalisation pour enregistrer les choses. Souvent, le message à imprimer sur la console est également enregistré. –

+1

Vous pouvez configurer le module de journalisation pour ce faire. Utilisez simplement plusieurs gestionnaires et/ou enregistreurs avec les niveaux correspondants. –

+0

Le module de journalisation n'est pas conçu pour une interface utilisateur textuelle .. interagissant avec l'utilisateur. Ex: write_to_terminal peut interagir avec une barre de progression déjà affichée et même la cacher (juste bzr) –

Répondre

5

Quelque chose comme ça?

def multicall(*functions): 
    def call_functions(*args, **kwds): 
     for function in functions: 
      function(*args, **kwds) 
    return call_functions 

Et si vous voulez agréger les résultats:

ont été suggérées
def multicall(*functions): 
    def call_functions(*args, **kwds): 
     return [function(*args, **kwds) for function in functions] 
    return call_functions 

EDIT

Décorateurs; dans ce cas, il ressemblerait à ceci:

def appendcalls(*functions): 
    def decorator(decorated_function): 
     all_functions = [decorated_function] + list(functions) 
     def call_functions(*args, **kwds): 
      for function in all_functions: 
       function(*args, **kwds) 
     return call_functions 
    return decorator 


LOG = logging.getLogger(__name__) 

@appendcalls(LOG.info) 
def info(fmt, *args): 
    print fmt % args 

info('Hello %s', 'guido') 

appendcalls() prend un certain nombre de fonctions à appeler après la fonction décorée. Vous voudrez peut-être implémenter le décorateur différemment, en fonction de la valeur de retour que vous voulez - l'original de la fonction décorée, une liste de tous les résultats de la fonction ou rien du tout.

+0

Il semble que même 'functools' n'aide pas à éviter d'écrire moi-même. –

+0

En fait, je veux conserver l'original 'info' (' write_to_terminal' dans mon exemple) et fournir les nouvelles informations (qui appelle aussi LOG) * en plus de * la version existante qui n'appelle pas LOG. '@ appendcalls' ne conserve pas la fonction d'origine. Par exemple, je ne veux pas "ajouter" une fonction à une autre .. mais créer une fonction * new * qui appelle N nombre d'autres fonctions passant les mêmes arguments. –

+0

@snd, dans ce cas vous ne pouvez pas utiliser un décorateur (qui par définition réaffecte le nom de la fonction qu'il décore!), Et la première partie de la réponse de @ Steef (avant le Edit :) est ce que vous cherchez. Et oui, functools n'offre pas ce HOF rarement nécessaire, facile à écrire (ni un trillion d'autres, d'ailleurs!) –

1

Vous pourriez vous pencher sur les décorateurs Python.

Une description claire est ici: http://www.artima.com/weblogs/viewpost.jsp?thread=240808

+0

+1, cela ressemble à une excellente utilisation pour les décorateurs –

+0

Comment exactement appliqueriez-vous un décorateur? sur plus d'une fonction? –

Questions connexes