Python Decorator Class with Arguments

I have a simple Python class that I want to use to add named hooks to the program I'm writing. I try to run the code below and I get the following output.


the code:

hooks = {}

class hook(object):
    def __init__(self, f, hook):
        if hook not in hooks:
            hooks[hook] = []

        hooks[hook].append({"module": f.__module__, "func": f})
        self.f = f

    def __call__(self, *args):
        f(*args)

@hook("test")
def testHook():
    print "hi"

Conclusion:

Traceback (most recent call last):                       
  File "<stdin>", line 1, in <module>                    
TypeError: __init__() takes exactly 3 arguments (2 given)

How can i fix this? I am using Python 2.7

+3
source share
1 answer

The syntax of your decorator is:

@hook("test")
def testHook():
    # ...

translates to:

def testHook():
    # ...

testHook = hook("test")(testHook)

therefore, only one argument is given. You need to rebuild your code to create a class decorator as the return value hook().

The following steps will work:

def hook(hookname):
    class HookDecorator(object):
        def __init__(self, f):
            if hookname not in hooks:
                hooks[hookname] = []

            hooks[hook].append({"module": f.__module__, "func": f})
            self.f = f

        def __call__(self, *args):
            return self.f(*args)

    return HookDecorator

__call__ self.f, f, . , hooks -.

; . :

from functools import wraps

def hook(hookname):
    def decorator(f):
        if hookname not in hooks:
            hooks[hookname] = []

        hooks[hookname].append({"module": f.__module__, "func": f})

        @wraps(f)
        def wrapper(*args):
            return f(*args)

        return wrapper

    return decorator
+6

All Articles