2012-04-05 7 views
2

Ich würde gerne einen neuen Dekorator anstelle von @wraps(f), die was auch immer mag Magie @wraps(f) würde tun, als etwas anderes. Wie würde ich das tun?Erweiterung der Funktionalität der functools.Wraps Dekorateur

Insbesondere, ich habe mehrere Dekorateure, die von der Form sind:

def decorator(f): 
    @wraps(f) 
    def wrapper(*args, **kwargs): 
     # does some stuff in here 
     return f(*args, **kwargs) 
    if not hasattr(wrapper, '_first_line'): 
     wrapper._first_line = inspect.getsourcelines(f)[1] 
    return wrapper 

Es scheint, wie ich in der Lage sollte ein Dekorateur wie @wraps_with_first_line(f) zu schaffen, die alles tun, dass @wraps(f) tut sowie if not hasattr(wrapper, '_first_line'): wrapper._first_line = inspect.getsourcelines(f)[1] .

Antwort

1

Wenn das, was Sie hinzufügen wollen, ist nicht bereits ein Attribut des Objekts gewickelt, dann können Sie diese verwenden:

def wraps_with_first_line(f): 
    def wrap(wrapper): 
     wrapper = wraps(f)(wrapper) 
     if not hasattr(wrapper, '_first_line'): 
      wrapper._first_line = inspect.getsourcelines(f)[1] 
     return wrapper 
    return wrap 

Wenn es ist bereits ein Attribut des verpackten Objekts, verwenden Svens Methode.

+0

Ich habe am Ende eine Mischung aus deiner Antwort und Sven's verwendet, aber es fühlte sich mehr wie deine an. – Isaac

3

Sie sollten eher der guten Praxis folgen, ein Attribut __wrapped__ hinzuzufügen, das auf die umbrochene Funktion verweist, als einzelne Attribute dieser umbrochenen Funktion hinzuzufügen. New versions von functools.wraps() tun dies automatisch, aber wenn Sie eine ältere Version von Python verwenden als 3,2, können Sie leicht wraps() Kü erweitern __wrapped__ hinzuzufügen:

def my_wraps(wrapped, **kwargs): 
    def decorator(wrapper): 
     functools.update_wrapper(wrapper, wrapped, **kwargs) 
     wrapper.__wrapped__ = wrapped 
    return decorator 

bearbeiten: Hier ist eine Funktion, die Extrakte die ursprüngliche Funktion aus eine möglicherweise mehrfach dekoriert Funktion:

def orig_function(f): 
    try: 
     while True: 
      f = f.__wrapped__ 
    except AttributeError: 
     return f 
+0

In meinem speziellen Anwendungsfall habe ich einige Funktionen, die mehr als einmal dekoriert/verpackt sind - in diesen Fällen würde mich "some_func .__ wrapped__" auf den Zwischen-Wrapper verweisen, oder? Könnte ich in meinem ursprünglichen Code so etwas wie das 'if not hasattr ...' machen, um '_original_wrapped' oder so etwas zu setzen? (Ist das effektiv, was in [Agf's Antwort] (http://stackoverflow.com/a/10032158/291280) getan wird?) – Isaac

+0

@Isaac: Sie könnten auch eine Dienstprogrammfunktion schreiben, die die ursprüngliche Funktion extrahiert, indem Sie der Kette von 'folgen __wrapped__' Argumente. Natürlich können Sie in 'Decorator()' über was auch immer Sie wollen. –

Verwandte Themen