decorator für normale Funktion und Klassen Funktion

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Hab sowas:

Code: Alles auswählen

def pylucid_objects(view_function):
    @wraps(view_function)
    def _inner(request, *args, **kwargs):
        response = resolve_pagetree_url(request)
        if response:
            return response

        # Create initial context object
        request.PYLUCID.context = RequestContext(request)

        return view_function(request, *args, **kwargs)
    return _inner


def class_based_pylucid_objects(view_function):
    @wraps(view_function)
    def _inner(cls, request, *args, **kwargs):
        response = resolve_pagetree_url(request)
        if response:
            return response

        # Create initial context object
        request.PYLUCID.context = RequestContext(request)

        return view_function(cls, request, *args, **kwargs)
    return _inner
Machen beide das selbe, aber der eine ist für normale Funktion und der andere für Klassen Funktion, also bsp:

Code: Alles auswählen

@pylucid_objects
def foo(request):
    pass

class ClassView(object):
    @class_based_pylucid_objects
    def foo(self, request):
        pass
Also beide machen das selbe, aber weil die Signatur anders ist, musste ich zwei machen.
Wie kann man das vereinfachen?

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
zikzak
User
Beiträge: 21
Registriert: Sonntag 22. September 2013, 07:28
Wohnort: Sipbachzell, Österreich

Die Funktion kannst Du Dir sparen, Zugriff über die Klasse (bzw. umgekehrt falls die Klasse sonst nichts hergibt):

Code: Alles auswählen

def dekorierer (f):
    print ("dekoriert")
    return f


class Kongret (object):
    @dekorierer
    @classmethod
    def inner(request, *args, **kwargs):
        print (request, *args, **kwargs)

def funktion (request):
    return Kongret.inner(request)

class Vererbt(Kongret):
    pass
    
a = Kongret()
s = a.inner("über Klasse")
b = funktion("über Funktion")
Kongret.inner("direkt über Methode von Klasse")

v = Vererbt()
v.inner("vererbt")
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Ich verstehe nicht wirklich, wie mir das helfen soll?

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

@jens:
Wenn Du mit vereinfachen meinst, dass Du nur einen Dekorator haben willst - nimm doch `cls` und `request` aus der signatur raus. Dann landen beide in den generischen Parametern (`args` oder `kwargs` je nach Aufruf), da kannst Du sie wieder rausfischen und getrennt behandeln.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Man könnte die Konstruktion zusammenfassen. Die beiden verschiedenen Namen bleiben dabei natürlich noch immer bestehen. Besonders hübsch ist die Lösung aber nicht:

Code: Alles auswählen

def make_function(request_index):
    def function(view_function):
        @wraps(view_function)
        def _inner(*args, **kwargs):
            request = args[request_index]
             
            response = resolve_pagetree_url(request)
            if response:
                return response
        
            # Create initial context object
            request.PYLUCID.context = RequestContext(request)
        
            return view_function(*args, **kwargs)
        return _inner
    return function

pylucid_objects = make_function(0)
class_based_pylucid_objects = make_function(1)
Das Leben ist wie ein Tennisball.
Antworten