-1

I am learning to write the python decorators. Following are two examples.

Example 1:

def dec():
    def wrapper(func):
        print(func)
        return func

    return wrapper

@dec
def hello():
    print('hello')

Example 2:

def dec(name):
    def wrapper(fn):
        print(fn)
        return fn
    return wrapper

@dec('a')
def hello(x):
    print(x)

So my question is why the example 1 throws an exception that dec() takes 0 positional arguments but 1 was given while the example 2 works well.

L3viathan
  • 26,748
  • 2
  • 58
  • 81
lfc199471
  • 15
  • 2
  • 3
    In the first example, you need to call `dec` like this: `@dec()`. If you want to use it like you do, your decorator itself must take the function (i.e. no need for a wrapper). – L3viathan Jul 02 '19 at 12:12

1 Answers1

1

Bot examples are incorrect. the outer function of a decorator (dec in this case) must take an argument which is the function it decorates.

So example 1 should look like this:

def dec(func):
    def wrapper():
        print(func)
        return func

    return wrapper

@dec
def hello():
    print('hello')

hello()

Example two while doesn't crash immediately, would if you tried to call hello (the decorated function). For a decorator to take an argument you need another level of nesting. So example 2 should look like this:

def dec_args(name):
    def dec(func):
        def wrapper():
            print(func)
            print(name)
            return func

        return wrapper
    return dec

@dec_args('a')
def hello():
    print('hello')

hello()

The inner decorator function (wrapper) should take the argument that are passed to the decorated function (hello). In these cases you don't have any Also note that the wrapper function doesn't really need to return func. wrapper is essentially a replacement of func. That's what decorators do. They replace the function you decorate with the inner function of the decorator (by calling the outer function with the decorated function as an argument).

Eran
  • 2,324
  • 3
  • 22
  • 27