722 Stimmen

Dekorateure mit Parametern?

Ich habe ein Problem mit der Übertragung der Variablen insurance_mode durch den Decorator. Ich würde es mit der folgenden Decorator-Anweisung tun:

@execute_complete_reservation(True)
def test_booking_gta_object(self):
    self.test_select_gta_object()

aber leider funktioniert diese Anweisung nicht. Vielleicht gibt es eine bessere Möglichkeit, dieses Problem zu lösen.

def execute_complete_reservation(test_case,insurance_mode):
    def inner_function(self,*args,**kwargs):
        self.test_create_qsf_query()
        test_case(self,*args,**kwargs)
        self.test_select_room_option()
        if insurance_mode:
            self.test_accept_insurance_crosseling()
        else:
            self.test_decline_insurance_crosseling()
        self.test_configure_pax_details()
        self.test_configure_payer_details

    return inner_function

5 Stimmen

Dein Beispiel ist nicht syntaktisch korrekt. execute_complete_reservation erwartet zwei Parameter, aber du übergibst ihm nur einen. Dekorateure sind nur syntaktischer Zucker, um Funktionen in andere Funktionen einzuschließen. Siehe docs.python.org/reference/compound_stmts.html#function für die vollständige Dokumentation.

2voto

chen.wq Punkte 31

Definiere diese "decoratorize Funktion", um eine angepasste Dekorator Funktion zu generieren:

def decoratorize(FUN, **kw):
    def foo(*args, **kws):
        return FUN(*args, **kws, **kw)
    return foo

Verwende sie auf diese Weise:

    @decoratorize(FUN, arg1 = , arg2 = , ...)
    def bar(...):
        ...

2voto

Leon Chang Punkte 487

Hier ist ein Flask-Beispiel, bei dem Dekorateure mit Parametern verwendet werden. Angenommen, wir haben eine Route '/user/name' und möchten diese auf seine Startseite mappen.

def matchR(dirPath):
    def decorator(func):
        def wrapper(msg):
            if dirPath[0:6] == '/user/':
                print(f"Benutzerroute '{dirPath}' passt, rufe Funktion {func} auf")
                name = dirPath[6:]
                return func(msg2=name, msg3=msg)
            else:
                print(f"Eingegebener dirPath '{dirPath}' passt nicht zur Route '/user/'")
                return
        return wrapper
    return decorator

#@matchR('/Morgan_Hills')
@matchR('/user/Morgan_Hills')
def home(**kwMsgs):
    for arg in kwMsgs:
        if arg == 'msg2':
            print(f"In home({arg}): Hallo {kwMsgs[arg]}, willkommen zuhause!")
        if arg == 'msg3':
            print(f"In home({arg}): {kwMsgs[arg]}")

home('Dies ist Ihr Profil, gerendert wie in index.html.')

Ausgabe:

Benutzerroute '/user/Morgan_Hills' passt, rufe Funktion  auf
In home(msg2): Hallo Morgan_Hills, willkommen zuhause!
In home(msg3): Dies ist Ihr Profil, gerendert wie in index.html.

2voto

conmak Punkte 807

Dies ist ein großartiger Anwendungsfall für eine Currying-Funktion.

Curried-Funktionen verzögern im Wesentlichen den Aufruf einer Funktion, bis alle Eingaben bereitgestellt wurden.

Dies kann für eine Vielzahl von Dingen wie Wrapper oder funktionale Programmierung verwendet werden. In diesem Fall erstellen wir einen Wrapper, der Eingaben entgegennimmt.

Ich werde ein einfaches Paket pamda verwenden, das eine Curry-Funktion für Python enthält. Diese kann als Wrapper für andere Funktionen verwendet werden.

Installiere Pamda:

pip install pamda

Erstelle eine einfache curried Decorator-Funktion mit zwei Eingaben:

@pamda.curry()
def my_decorator(input, func):
    print ("Decorator wird ausgeführt")
    print(f"Eingabe: {input}")
    return func

Wende deinen Decorator mit der ersten bereitgestellten Eingabe auf deine Ziel-Funktion an:

@my_decorator('Hallo!')
def foo(input):
    print('Foo wird ausgeführt!')
    print(f"Eingabe: {input}")

Das gewrappte Funktions-Aufrufen:

x = foo('Tschüss!')

Alles zusammenfügen:

from pamda import pamda

@pamda.curry()
def my_decorator(input, func):
    print ("Decorator wird ausgeführt")
    print(f"Eingabe: {input}")
    return func

@my_decorator('Hallo!')
def foo(input):
    print('Foo wird ausgeführt!')
    print(f"Eingabe: {input}")

x = foo('Tschüss!')

Würde folgendes zurückgeben:

Decorator wird ausgeführt
Eingabe: Hallo!
Foo wird ausgeführt!
Eingabe: Tschüss!

0voto

Gulzar Punkte 16632

Ich denke, ein funktionierendes, realweltliches Beispiel mit Anwendungsbeispielen des allgemeinsten Anwendungsfalls kann hier wertvoll sein.


Im Folgenden befindet sich ein Decorator für Funktionen, der beim Betreten und Verlassen der Funktion ein Log erstellt.

Parameter steuern, ob Eingabe- und Ausgabewerte gedruckt werden sollen, das Log-Level usw.

import logging 
from functools import wraps

def log_in_out(logger=logging.get_logger(), is_print_input=True, is_print_output=True, is_method=True, log_level=logging.DEBUG):
    """
    @param logger-
    @param is_print_input- Schaltet das Drucken der Eingabeargumente ein oder aus
    @param is_print_output- Schaltet das Drucken der Ausgabewerte ein oder aus
    @param is_method- True für Methoden, False für Funktionen. Verhindert, dass "self" gedruckt wird, falls is_print_input==True
    @param log_level-

    @returns- ein Decorator, der zu logger loggt, wenn die dekorierte Funktion betreten oder verlassen wird.
    Verschandele deinen Code nicht!
    """

    def decor(fn):
        @wraps(fn)
        def wrapper(*args, **kwargs):
            if is_print_input:
                logger.log(
                    msg=f"Eingetreten in {fn.__name__} mit args={args[1:] if is_method else args}, kwargs={kwargs}",
                    level=log_level
                )
            else:
                logger.log(
                    msg=f"Eingetreten in {fn.__name__}",
                    level=log_level
                )

            result = fn(*args, **kwargs)

            if is_print_output and result is not None:
                logger.log(
                    msg=f"Verlassen {fn.__name__} mit Ergebnis {result}",
                    level=log_level,
                )
            else:
                logger.log(
                    msg=f"Verlassen {fn.__name__}",
                    level=log_level
                )

            return result

        return wrapper

    return decor

Anwendung:

 @log_in_out(is_method=False, is_print_input=False)
    def foo(a, b=5):
        return 3, a

foo(2) --> druckt

Eingetreten in foo
Verlassen foo mit Ergebnis (3, 2)

    class A():
        @log_in_out(is_print_output=False)
        def bar(self, c, m, y):
            return c, 6

a = A() a.bar(1, 2, y=3) --> druckt

Eingetreten in bar mit args=(1, 2), kwargs={y:3}
Verlassen bar

-1voto

SuperNova Punkte 20412

Wenn sowohl die Funktion als auch der Dekorator Argumente benötigen, können Sie den folgenden Ansatz verfolgen.

Zum Beispiel gibt es einen Dekorator namens decorator1, der ein Argument annimmt

@decorator1(5)
def func1(arg1, arg2):
    print (arg1, arg2)

func1(1, 2)

Wenn das Argument für decorator1 dynamisch sein muss oder beim Aufruf der Funktion übergeben wird,

def func1(arg1, arg2):
    print (arg1, arg2)

a = 1
b = 2
seconds = 10

decorator1(seconds)(func1)(a, b)

In dem obigen Code

  • seconds ist das Argument für decorator1
  • a, b sind die Argumente von func1

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