4

I'm trying to figure out why i need a one more nested function when using decorators. Here is an example:

 def func(f):
    def deco(*args, **kwargs):
        return f(*args, **kwargs)
    return deco

@func
def sum(a, b):
    return a+b

print sum(5, 10)

Code works, everything is fine. But why do i need to create nested "deco" function? Let's try without it:

def func(f):
    return f(*args, **kwargs)

@func
def sum(a, b):
    return a+b

print sum(5, 10)

Code fails.

So there are three questions:

  1. Why second sample does not works?
  2. Why args,kwargs are "magically" appears if we are using a nested function?
  3. What can i do, to make 2nd sample work? Except nesting another function, ofcourse.
vaultah
  • 44,105
  • 12
  • 114
  • 143
user
  • 51
  • 2
  • 3
    A decorator should return a function not the result of a function. In your first example, it returns a function ... In the second, it returns whatever your function f returns. – Julien Spronck Apr 06 '15 at 15:45
  • 1
    And what about 2nd and 3rd questions? – user Apr 06 '15 at 15:52
  • `*args` and `**kwargs` do not appear "magically", the arguments will only be defined once you call your decorated function (http://stackoverflow.com/questions/36901/what-does-double-star-and-star-do-for-python-parameters) – Julien Spronck Apr 06 '15 at 15:57
  • In short: Because the contract for decorators is that they are function factories: They take a function and return a new function. In your second example, your `func(f)` returns the *result of a function call*. But the decorator needs to return a *function* (that hasn't been called yet). – Lukas Graf Apr 06 '15 at 15:59
  • Note: @func is just some syntactic sugar for `sum = func(sum)`, `args` and `kwargs` only matter when you call this new definition of `sum`. – AChampion Apr 06 '15 at 16:14

1 Answers1

3
  1. Why second sample does not works?

    Because you are calling the function on the return, you are not returning a function.

  2. Why args,kwargs are "magically" appears if we are using a nested function?

    They don't appear magically, we are declaring them, as in:

    def deco(*args, **kwargs):
    

    These are generic, and will match any function signature (argument list). You don't have to call them args and kwargs, that's just a convention, you could call them sharon and tracy.

  3. What can i do, to make 2nd sample work? Except nesting another function, ofcourse.

    Well you don't say what you expect the 2nd sample to do. But I guess to turn it into a decorator then:

    def func(f):
        return f
    

    But that's not doing a lot!

By the way, it is usually a bad idea to override an existing Python builtin (sum) - you have to have a very good reason for that.

cdarke
  • 42,728
  • 8
  • 80
  • 84