370 Stimmen

Was sind einige häufige Verwendungszwecke für Python-Dekoratoren?

Ich halte mich zwar für einen einigermaßen kompetenten Python-Programmierer, aber ein Aspekt der Sprache, den ich noch nie verstanden habe, sind Dekoratoren.

Ich weiß, was sie sind (oberflächlich), ich habe Tutorials, Beispiele, Fragen auf Stack Overflow gelesen, und ich verstehe die Syntax, kann meine eigenen schreiben, verwende gelegentlich @classmethod und @staticmethod, aber es kommt mir nie in den Sinn, einen Decorator zu verwenden, um ein Problem in meinem eigenen Python-Code zu lösen. Ich bin nie auf ein Problem gestoßen, bei dem ich dachte: "Hmm...das sieht aus wie eine Aufgabe für einen Dekorator!"

Ich frage mich also, ob ihr vielleicht ein paar Beispiele nennen könntet, wo ihr Dekoratoren in euren eigenen Programmen verwendet habt, und hoffentlich habe ich einen "A-ha!"-Moment und bekommen. sie.

141voto

RSabet Punkte 5884

Ich verwende Dekorateure hauptsächlich für Timing-Zwecke

def time_dec(func):

  def wrapper(*arg):
      t = time.clock()
      res = func(*arg)
      print func.func_name, time.clock()-t
      return res

  return wrapper

@time_dec
def myFunction(n):
    ...

103voto

John Fouhy Punkte 39035

Ich habe sie für die Synchronisierung verwendet.

import functools

def synchronized(lock):
    """ Synchronization decorator """
    def wrap(f):
        @functools.wraps(f)
        def newFunction(*args, **kw):
            lock.acquire()
            try:
                return f(*args, **kw)
            finally:
                lock.release()
        return newFunction
    return wrap

Wie in den Kommentaren erwähnt, können Sie seit Python 2.5 eine with Anweisung in Verbindung mit einer threading.Lock (o multiprocessing.Lock seit Version 2.6), um die Implementierung des Dekorators zu vereinfachen:

import functools

def synchronized(lock):
    """ Synchronization decorator """
    def wrap(f):
        @functools.wraps(f)
        def newFunction(*args, **kw):
            with lock:
                return f(*args, **kw)
        return newFunction
    return wrap

Unabhängig davon verwenden Sie es dann so:

import threading
lock = threading.Lock()

@synchronized(lock)
def do_something():
  # etc

@synchronzied(lock)
def do_something_else():
  # etc

Im Grunde genommen stellt es nur lock.acquire() / lock.release() auf beiden Seiten des Funktionsaufrufs.

81voto

Simon Punkte 11090

Ich verwende Dekoratoren zur Typüberprüfung von Parametern, die über eine RMI an meine Python-Methoden übergeben werden. So muss ich nicht immer wieder den gleichen Hokuspokus mit dem Zählen von Parametern und dem Auslösen von Ausnahmen wiederholen.

Zum Beispiel anstelle von:

def myMethod(ID, name):
    if not (myIsType(ID, 'uint') and myIsType(name, 'utf8string')):
        raise BlaBlaException() ...

Ich erkläre nur:

@accepts(uint, utf8string)
def myMethod(ID, name):
    ...

y accepts() erledigt die ganze Arbeit für mich.

53voto

cdleary Punkte 66512

Dekoratoren werden für alles verwendet, was Sie transparent mit zusätzlicher Funktionalität "umhüllen" wollen.

Django verwendet sie für das Wrapping "Login erforderlich"-Funktionalität bei Ansichtsfunktionen als auch für Registrierung von Filterfunktionen .

Sie können Klassendekoratoren verwenden für Hinzufügen von benannten Protokollen zu Klassen .

Jede hinreichend generische Funktionalität, die Sie an das Verhalten einer bestehenden Klasse oder Funktion "anheften" können, ist ein faires Spiel für die Dekoration.

Außerdem gibt es eine Diskussion von Anwendungsfällen in der Newsgroup Python-Dev gezeigt von PEP 318 -- Dekoratoren für Funktionen und Methoden .

33voto

Torsten Marek Punkte 78610

Für Nosetests können Sie einen Decorator schreiben, der eine Unit-Test-Funktion oder -Methode mit mehreren Parametersätzen bereitstellt:

@parameters(
   (2, 4, 6),
   (5, 6, 11),
)
def test_add(a, b, expected):
    assert a + b == expected

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X