Ich verstehe, wie man einen Dekorateur schreibt.
Wie der Name schon sagt, ist ein Dekorateur ein Dekorateur. Was Sie dekorieren, ist eine Funktion, eine Funktion. Eine andere Methode.
Ich verstehe. Es ist schwer. Ich verstehe den Dekorateur.
Murmelte Takeshi und rannte los, als wäre er umgedreht worden. Aber das Signal begann zu blinken und hörte auf. Ja, er folgt den Verkehrsregeln.
Und denken Sie daran, die Zeit zu verlassen.
Die Menschheit ist das, was ich nutzen möchte, wenn ich schreiben kann. Wenn ich es jedoch tatsächlich verwenden möchte, weiß ich nicht, wo ich es verwenden soll. Ich kann mir keine effektive Verwendung vorstellen.
So eine Person.
Ja! Ich weiß es nicht einmal!
Nein, aber vielleicht habe ich ein wenig verstanden.
Warum einen Dekorateur benutzen?
Verwenden Sie Dekorateure für unerwünschte Redundanzbeseitigung und TROCKEN
Verwenden Sie Dekorateure, um die Lesbarkeit zu verbessern
Mir fällt so etwas ein. Dies wird oft als Vorteil der Verwendung erwähnt.
Das ist nichts falsch! Überwiegend richtig! Oh, ich bin sicher, dass es richtig ist!
Aber ich weiß nur nicht, wo ich es verwenden soll.
Weil es aus den oben genannten Gründen viele andere Möglichkeiten gibt, oder? Gibt es zum Beispiel Vererbung? Ist es in Ordnung, es so zu machen, wie es ist? Du bist daran gewöhnt, oder? Ich möchte nicht die Mühe machen, so etwas wie einen Dekorateur zu schreiben. Ich denke schon, aber beschweren Sie sich?
Denkst du? Denkst du nicht? Ich denke.
Warum also einen Dekorateur wagen?
Um darüber nachzudenken, müssen wir auf die ** Bedeutung ** der Verarbeitung des Codes achten. Das Fazit ist, dass wir Dekoratoren für die ** Trennung der Geschäftslogik ** verwenden.
Möglicherweise haben Sie ein Beispiel wie dieses als ersten Schritt beim Dekorieren gesehen.
from functools import wraps
def trace_func_call(func):
@wraps(func)
def wrapper(*arg):
print(func.__name__ + ' is called.')
return func(*arg)
return wrapper
@trace_func_call
def spam(s):
print((s + '!') * 5)
@trace_func_call
def ham(s):
print((s + '?') * 5)
spam('egg')
ham('sausage')
** Ausführungsergebnis **
spam is called.
egg!egg!egg!egg!egg!
ham is called.
sausage?sausage?sausage?sausage?sausage?
Ein Dekorateur, der es bei jedem Aufruf einer Funktion anzeigt.
Zu diesem Zeitpunkt ist die Rolle des Dekorateurs keine Geschäftslogik, nicht wahr? Das Beispiel ist sehr gut geeignet, aber die Verarbeitung, die Sie als Geschäftslogik ausführen möchten, ist die Verarbeitung der Funktionen "Spam" und "Ham", nicht wahr? Es ist ein beschissener Typ, der 5 Mal mit "!" Oder "?" Wiederholt. Als Argument.
Zu diesem Zeitpunkt ist das Anzeigen des Funktionsaufrufs nicht die Geschäftslogik, sondern die zu implementierende Logik, da sie für die Verwaltung erforderlich ist. Ihre Logik ist semantisch anders.
Sie können Dekoratoren verwenden, um die Verwaltungslogik von der Geschäftslogik zu trennen. Mit anderen Worten, basierend auf dem, was Sie tun möchten, sind Dekorateure diejenigen, die die Absicht erkennen, die Geschäftslogik, die der Hauptzweck des Codes ist, auf saubere Weise von der Verwaltungslogik zu trennen. Natürlich möchte ich nicht sagen, dass dies die einzige Rolle des Dekorateurs ist, aber es gibt einen großartigen Vorschlag zur Verwendung des Dekorateurs.
Weiter ist etwas praktischer. Dies ist ein Beispieldekorateur aus Raymond Hettingers Vortrag ** "Code in schönes, idiomatisches Python verwandeln" ** auf der PyCon US 2013.
Beginnen wir mit dem ursprünglichen "weniger wünschenswerten" Code.
def web_lookup(url, saved={}):
if url in saved:
return saved[url]
page = urllib.urlopen(url).read()
saved[url] = page
return page
Klicken Sie hier, um eine bessere Version des obigen Codes mit einem Dekorateur zu erhalten.
def cache(func):
saved = {}
@wraps(func)
def newfunc(*args):
if args in saved:
return saved[args]
result = func(*args)
saved[args] = result
return result
return newfunc
@cache
def web_lookup(url):
return urllib.urlopen(url).read()
Die Funktion "web_lookup" ist eine Funktion zum Abrufen der Webseite der angegebenen URL. Zu diesem Zeitpunkt hat es eine Funktion zum Zwischenspeichern der erfassten Seiten.
Es ist ein sehr kurzer Code, aber Sie können sehen, dass die Funktionalität dieses Codes semantisch wie folgt unterteilt ist:
--Geschäftslogik -> Ruft die Webseite der angegebenen URL ab
Im ursprünglichen Code wird die Caching-Funktionalität durch ein Wörterbuch von Argumenten bereitgestellt, die an die Funktion "web_lookup" übergeben werden. Mit anderen Worten, die Funktion selbst ist eine Implementierung, die die Funktionalität von Geschäftslogik und Verwaltungslogik beinhaltet.
Im Gegensatz dazu implementiert die Funktion in besserem Code nur die Geschäftslogik, und die Verwaltungslogik wird vom geschlossenen Dekorateur implementiert. Auf diese Weise werden Sie feststellen, dass die Geschäftslogik klar getrennt ist und der Code besser lesbar und wartbar ist.
Die Menge an Code hat mit der Implementierung von Dekorateuren zugenommen, aber ich denke, dass es ein sehr pythonisches Gefühl ist, ihn "schönen Code" zu nennen.
Übrigens sind diese Cash Decorator-Muster Standardmuster, daher ist es nicht schwierig und Sie sollten es auf jeden Fall versuchen.
Übrigens denke ich, dass der Code der Folie der von mir zitierten Vorlesung falsch ist ... Also ändere ich den Code, den ich oben geschrieben habe. Dies ist der Dekorateur. Du liegst falsch, richtig? https://speakerdeck.com/pyconslides/transforming-code-into-beautiful-idiomatic-python-by-raymond-hettinger-1
Dann noch einer.
Besonders wenn 2.x verwendet wird und der Zeichencode der Eingabe unbekannt ist, bin ich es wirklich leid, mit der Zeichenfolge umzugehen, irgendwie zu dekodieren, irgendwie uni-kodo usw., also verwende ich bei der internen Verarbeitung Chardet mit einem Dekorateur Lassen Sie uns alles Unicode machen und verarbeiten.
Dies kann beim Schreiben eines kleinen Werkzeugs hilfreich sein.
import chardet
def unicode_conv(func):
def wrapper(*args):
f = lambda x: x.decode(chardet.detect(x)['encoding'])
args = [f(arg) if type(arg) != unicode else arg for arg in args]
return func(*args)
return wrapper
def funcA(*args):
for arg in args:
print(repr(arg))
@unicode_conv
def funcB(*args):
for arg in args:
print(repr(arg))
funcA('shrubbery')
funcB('shrubbery')
funcB(u'shrubbery')
** Ausführungsergebnis **
'shrubbery'
u'shrubbery'
u'shrubbery'
Recommended Posts