2010-05-02 3 views
1

Vous devez créer une classe qui fera tout ce que la fonction "fusionner". En classe je vais changer, traiter et ajouter de nouveaux arguments.Fusionner la fonction de décoration en classe

def merge(*arg, **kwarg): # get decorator args & kwargs 
    def func(f): 
     def tmp(*args, **kwargs): # get function args & kwargs  
      kwargs.update(kwarg) # merge two dictionaries 
      return f(*args, **kwargs) # return merged data 
     return tmp 
    return func 

Utilisation:

@other_decorator # return *args and **kwarg 
@merge(list=['one','two','three']) # need to merge with @other_decorator 
def test(*a, **k): # get merged args and kwargs 
    print 'args:', a 
    print 'kwargs:', k 
+0

Qu'est-ce que vous voulez le décorateur de classe à faire? L'exemple montre seulement un décorateur de fonction. – interjay

+0

Besoin de créer une classe qui fera toutes les choses comme la fonction "fusion". En classe je vais changer, traiter et ajouter de nouveaux arguments. Fonction "fusionner" fonctionne, mais j'ai trop de sous-fonctions de processus. – SyetemHog

Répondre

2

Je ne suis pas sûr que je reçois tout à fait ce que vous demandez. Votre implémentation fonctionne correctement et vous n'aurez pas deux niveaux d'indirection si vous voulez créer un décorateur paramétré de n'importe quel type.

Pour faire fusionner une classe, vous pouvez le faire

class Merge(object): 
    def __init__(self, **extra_kws): 
     self.extra_kws = extra_kws 
    def __call__(self, function): 
     def _wrapper(*args, **kws): 
      kws.update(self.extra_kws) 
      return function(*args, **kws) 
     return _wrapper 

Ensuite, vous pouvez le faire:

@Merge(foo='bar') 
def test(*args, **kws): 
    print *args 
    print **kws 

Mais vous avez dit que vous voulez ajouter le changement et traiter de nouveaux arguments. Donc, vous voulez probablement que le décorateur lui-même soit en ligne pour que vous puissiez le faire:

test.extra_kws['sun'] = 'dock' 

Après l'application du décorateur. Dans ce cas, vous ne voulez probablement pas fusionner pour être une classe, mais vous voulez générer une classe, de sorte que test est remplacé par l'instance modifiable:

def merge(**extra_kws): 
    class _Merge(object): 
     def __init__(self, function): 
      self.extra_kws = extra_kws 
      self.function = function 
     def __call__(self, *args, **kws): 
      kws.update(self.extra_kws) 
      return self.function(*args, **kws) 
    return _Merge 

@merge(foo='bar') 
def test(*args, **kws): 
    print 'args:', args 
    print 'kws:', kws 

test(sun='dock') 
test.extra_kws['trog'] = 'cube' 
test(sun='dock') 

Cela vous permet de changer les mots-clés sur une fonction décorée particulière plus tard.

Vous pouvez également faire la même chose avec des arguments de fonction sans cours:

def merge(**extra_kws): 
    def _decorator(function): 
     def _wrapper(*args, **kws): 
      kws.update(_wrapper.extra_kws) 
      return function(*args, **kws) 
     _wrapper.extra_kws = extra_kws 
     return _wrapper 
    return _decorator 

@merge(foo='bar') 
def test(*args, **kws): 
    print 'kws:', kws 

test(sun='dock') 
test.extra_kws['trog'] = 'cube' 
test(sun='dock') 
Questions connexes