Frage
Wie kann ich einen Dekorateur schön schreiben?
In bestimmten Themen umfassen: Kompatibilität mit anderen Dekorateure, die Erhaltung von Unterschriften, etc.
.Ich möchte die Abhängigkeit von dem Dekorateur-Modul, wenn möglich zu vermeiden, aber wenn es genügend Vorteile wäre, dann würde ich es in Betracht ziehen.
ähnlich
- Erhaltung Unterschriften von dekorierten Funktionen - viel spezifischere Frage. Die Antwort ist die Drittanbieter-Dekorateur-Modul zu verwenden, um den Dekorateur mit @ decorator.decorator Anmerkungen versehen
Lösung
einen guten Dekorateur zu schreiben, ist es nicht anders dann eine gute Funktion zu schreiben. Das heißt, im Idealfall, Docstrings und sicherstellen, dass mit dem Dekorateur in Ihrem Test-Framework enthalten ist.
Sie sollten auf jeden Fall entweder die decorator
Bibliothek oder, besser, der functools.wraps()
Dekorateur in der Standardbibliothek (seit 2.5) verwendet werden.
Darüber hinaus ist es am besten Ihre Dekorateure zu halten eng fokussiert und gut gestaltet. Nicht *args
oder **kw
verwenden, wenn Ihr Dekorateur spezifische Argumente erwartet. Und Sie füllen, welche Argumente Sie erwarten, so statt:
def keep_none(func):
def _exec(*args, **kw):
return None if args[0] is None else func(*args, **kw)
return _exec
... Verwendung ...
def keep_none(func):
"""Wraps a function which expects a value as the first argument, and
ensures the function won't get called with *None*. If it is, this
will return *None*.
>>> def f(x):
... return x + 5
>>> f(1)
6
>>> f(None) is None
Traceback (most recent call last):
...
TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'
>>> f = keep_none(f)
>>> f(1)
6
>>> f(None) is None
True"""
@wraps(func)
def _exec(value, *args, **kw):
return None if value is None else func(value, *args, **kw)
return _exec
Andere Tipps
Verwenden functools den Namen und doc zu bewahren. Die Signatur wird nicht beibehalten werden.
Direkt vom doc .
>>> from functools import wraps
>>> def my_decorator(f):
... @wraps(f)
... def wrapper(*args, **kwds):
... print 'Calling decorated function'
... return f(*args, **kwds)
... return wrapper
...
>>> @my_decorator
... def example():
... """Docstring"""
... print 'Called example function'
...
>>> example()
Calling decorated function
Called example function
>>> example.__name__
'example'
>>> example.__doc__
'Docstring'