Passing parameters thru decorators

Peter Otten __peter__ at web.de
Wed Apr 12 17:22:33 EDT 2017


andrew.holway at otternetworks.de wrote:

> Hi,
> 
> I'm trying to work out how to pass parameters through decorators:
> 
> class Meow():
> 
>     def __init__(self, arg1, arg2):
>         print("INIT ClassBasedDecoratorWithParams")
>         print(arg1)
>         print(arg2)
> 
>     def makebold(self, fn):
>             def wrapped():
>                 return "<b>" + fn() + "</b>"
>             return wrapped
> 
> banana = Meow("foo", "bar")
> @banana.makebold("foobar")
> 
> def hello():
>     return "hello world"
> 
> print(hello())
> 
> 
> Returns error:
> INIT ClassBasedDecoratorWithParams
> Traceback (most recent call last):
> foo
>   File "/Users/andrew/PycharmProjects/untitled3/meow5.py", line 15, in
>   <module>
> bar
>     @banana.makebold("foobar")
> TypeError: wrapped() takes 0 positional arguments but 1 was given
> 
> 
> so I add a var to wrapped:
> 
>     def makebold(self, fn):
>             def wrapped(flibble):
>                 print(flibble)
>                 return "<b>" + fn() + "</b>"
>             return wrapped
> 
> Returns error:
> INIT ClassBasedDecoratorWithParams
> Traceback (most recent call last):
> foo
> bar
>   File "/Users/andrew/PycharmProjects/untitled3/meow5.py", line 16, in
>   <module>
> <function hello at 0x1029198c8>
>     @banana.makebold("foobar")
>   File "/Users/andrew/PycharmProjects/untitled3/meow5.py", line 11, in
>   wrapped
>     return "<b>" + fn() + "</b>"
> TypeError: 'str' object is not callable
> 
> This is confusing me. How do I get hold of the "foobar" string so I can
> use it in the decorator?

You need one more level of indirection:

class Meow():
    def __init__(self, arg1, arg2):
        print("INIT ClassBasedDecoratorWithParams")
        print(arg1)
        print(arg2)

    def makebold(self, flibble):
        def decorator(fn):
            def wrapped():
                print("flibble =", flibble)
                return "<b>" + fn() + "</b>"
            return wrapped
        return decorator

banana = Meow("foo", "bar")

@banana.makebold("foobar")
def hello():
    return "hello world"

print(hello())





More information about the Python-list mailing list