2010-05-03 6 views
3

je veux utiliser une fonction d'un autre module comme décorateur, mais je besoin de manipuler espace de noms global du module en cours.Utilisation des fonctions de décorateur python d'un module différent

Par exemple, je veux être en mesure d'aller de ceci:

class SomeClass: 
    pass 

root = SomeClass 

à ceci:

from othermodule import decorator 

@decorator 
class Someclass: 
    pass 

Toutes les idées?

+1

Est-ce pas ce code déjà un travail? – muckabout

+0

Je pense qu'il veut que le code dans le décorateur définisse une variable racine dans la portée globale de la classe d'origine. J'ai peur que ce soit contre tout python. –

+0

Vous pourriez avoir une fonction qui retourne le décorateur qui accepte vos globals. –

Répondre

0

C'est un peu hacky, mais essayez ceci dans othermodule.py:

import sys 
def decorator(cls): 
    mod = __import__(cls.__module__) 
    mod.root = cls 
+0

Ouais ça a marché, merci. En fait, j'ai fini par utiliser mod = sys.modules [cls .__ module__] parce que l'appel __import__ n'a renvoyé que le module de niveau supérieur (cls .__ module__) avait 4 niveaux de profondeur - ie mod1.mod2.mod3.mod4 –

+0

Incidemment, 'mod = __import__ (cls .__ module__, {}, {}, ('*',)) 'retournerait le module mod4, pas le paquet mod1 le plus externe –

+0

Ceci est une réponse directe (bien que sujette à erreur pour les paquets et autres), mais très effrayant code. De plus, c'est stupide d'utiliser 'setattr' avec des littéraux de chaînes. 'setattr (foo, 'bar', baz)' est orthographié 'foo.bar = baz'. –

4

Cela fonctionne déjà:

from othermodule import decorator 

@decorator 
class Someclass: 
    pass 

Il suffit de mettre en othermodule.py:

def decorator(cls): 
    #.... do something with cls 
    return cls 
+0

Oui, je sais que cela fonctionne en général, mais c'est le fait que je veux un décorateur du module importé pour définir une variable dans la portée globale du module d'origine qui cause des problèmes. –

4

Avoir un décorateur modifier l'espace de noms global si un module, encore moins un autre module, est mauvais et jamais nécessaire. Le code qui mute des globales lointains est difficile à lire et à maintenir. Vous devriez certainement envisager de modifier votre conception pour éviter l'état global mutable et en particulier l'affectation implicite.

0

Au lieu d'un décorateur directe, vous pouvez avoir une fonction qui retourne un décorateur et accepte les globals de votre module:

def decorator(globals): 
    def dec(cls): 
     globals.root = cls 
     return cls 
    return dec 

@decorator(globals()) 
class SomeClass: 
    ... 
Questions connexes