29 Stimmen

Decorator, der Funktionsaufrufdetails (Parameternamen und effektive Werte) ausgibt?

Ich möchte eine Funktion erstellen, die als Dekorator einer anderen Funktion die Details des Funktionsaufrufs ausgibt - Parameternamen und effektive Werte. Meine aktuelle Implementierung ist diese.

def describeFuncCall(func):
    """
    Decorator to print function call details.

    parameters names and effective values.
    """

    def wrapper(*func_args, **func_kwargs):
        print "func_code.co_varnames =", func.func_code.co_varnames
        print "func_code.co_argcount =", func.func_code.co_argcount
        print "func_args =", func_args
        print "func_kwargs =", func_kwargs
        params = []
        for argNo in range(func.func_code.co_argcount):
            argName = func.func_code.co_varnames[argNo]
            argValue = (
                func_args[argNo]
                if argNo < len(func_args)
                else func.func_defaults[argNo - func.func_code.co_argcount]
            )
            params.append((argName, argValue))
        for argName, argValue in func_kwargs.items():
            params.append((argName, argValue))
        params = [argName + " = " + repr(argValue)
                  for argName, argValue in params]
        print (func.__name__ + " ( " + ", ".join(params) + " )")
        return func(*func_args, **func_kwargs)

    return wrapper

@describeFuncCall
def test(a, b=4, c="blah-blah", *args, **kwargs):
    pass

test(1)
# test(1, 3)
# test(1, d = 5)
test(1, 2, 3, 4, 5, d=6, g=12.9)

Irgendwie funktioniert es, aber mit einigen Fehlern:

Für Anrufe

test(1, 2, 3, 4, 5, d = 6, g = 12.9)

Es druckt

test ( a = 1, b = 2, c = 3, d = 6, g = 12.9 ) .

Das erwartete Ergebnis ist

test ( a = 1, b = 2, c = 3, args = [4, 5], kwargs = {'d': 6, 'g': 12.9} )

Ich bin hier hängengeblieben. Können Sie mir helfen, die richtige Lösung zu finden?

0voto

Paritosh Punkte 53

Der Beitrag ist zwar schon etwas älter, aber ich wollte meinen Teil dazu beitragen. Die von warvariuc angegebene Lösung funktioniert nicht in allen Fällen. Wenn eine Methode Standardwerte sowie wir senden benannte Argumente während des Aufrufs, gibt es nicht ordnungsgemäße Ausgabe. z.B. erhalten wir zwei Werte von b.

test(1, b = 5)
test (a = 1, b = 4, c = 'blah-blah', kwargs = {'b': 5} )

Ich füge meinen geänderten Code hinzu.

def print_args(func):
    """
    Function to print all args of decorated function
    """

    def wrapper(*func_args, **func_kwargs):
        arg_names = func.__code__.co_varnames[:func.__code__.co_argcount]
        args = func_args[:len(arg_names)]
        defaults = func.__defaults__ or ()
        args = args + defaults[len(defaults) - (func.__code__.co_argcount - len(args)):]
        params = zip(arg_names, args)
        new_arg_list = [list(i) for i in params]
        for key in func_kwargs:
            for param in new_arg_list:
                if key == param[0]:
                    param[1] = func_kwargs[key]
        new_arg_list = [tuple(i) for i in new_arg_list]
        result = func(*func_args, **func_kwargs)
        print(f'{func.__name__} (' + ', '.join('%s = %r' % p for p in new_arg_list) + f'): {result}')

        return result

    return wrapper

@print_args
def test_params(a=7,b=5):
    pass

test_params(a=3)

Ausgabe

test_params (a = 3, b = 5)

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