Python class decorators with arguments, but decorated function is not being run

StackOverflow https://stackoverflow.com/questions/21339234

  •  02-10-2022
  •  | 
  •  

Вопрос

I've got this working for the most part. I want to have a class decorator (Decorator class) that accepts arguments (greeting and farewell) that can be used to wrap a method on an object (an instance of Person).

Everything is working fine, except... the original command function on the Person class is never run! If I manually call the function using something like

output = getattr(instance, func.func_name)(command, *args, **kwargs)

I get infinite recursion.

How do I do this? The full code is listed below:

import functools

class Decorator(object):
    def __init__(self, greeting, farewell, *args, **kwargs):
        print "initing"
        self.greeting = greeting
        self.farewell = farewell

    def __call__(self, func, *args, **kwargs):
        print "CALLING"

        @functools.wraps(func)
        def wrapper(instance, command, *args, **kwargs):
            return "%s, %s! %s!\n%s, %s!" % (
                self.greeting,
                instance.name,
                command,
                self.farewell,
                instance.name
            )
        return wrapper

class Person(object):
    def __init__(self, name):
        self.name = name

    @Decorator("Hello", "Goodbye")
    def command(self, data):
        return data + "LIKE A BOSS"

s = Person("Bob")
print s.command("eat food")

Actual output:

initing
CALLING
Hello, Bob! eat food!
Goodbye, Bob!

Expected output:

initing
CALLING
Hello, Bob! eat food LIKE A BOSS!
Goodbye, Bob!
Это было полезно?

Решение

You never called func to get the original message:

def wrapper(instance, command, *args, **kwargs):
            original_value = func(instance, command) #call func here
            return "%s, %s! %s!\n%s, %s!" % (
                self.greeting,
                instance.name,
                original_value,
                self.farewell,
                instance.name
            )

Output:

initing
CALLING
Hello, Bob! eat food LIKE A BOSS!
Goodbye, Bob!

Другие советы

You must call func(data) somewhere in your wrapper to get the "LIKE A BOSS" result and add it to the expected output

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top