Reputation: 1276
I've been trying to understand decorators. I had understood them as a function that you pass other functions through, to modify some functionality. However, the following type error is returned. Could someone explain (A) Why this is not valid? and (B) How this code should be modified such that 12 is returned?
def dec(x):
return 2*x
@dec
def func(x,y):
return x*y
>>>
TypeError Traceback (most recent call last)
<ipython-input-89-355f941cfec0> in <module>
3
4 @dec
----> 5 def func(x,y):
6 return x*y
7
<ipython-input-89-355f941cfec0> in dec(x)
1 def dec(x):
----> 2 return 2*x
3
4 @dec
5 def func(x,y):
TypeError: unsupported operand type(s) for *: 'int' and 'function'
Upvotes: 0
Views: 156
Reputation: 1211
Your decorator is given a function as an argument and needs to return a function, not a value. For example:
def dec(fn):
def newfn(x, y):
return 2 * fn(x, y)
return newfn
The point is that I am returning a function that if called will call fn internally, multiply that result by two and return that.
A decorator replaces one function with another. So this:
@dec
def mult(x, y):
return x * y
is exactly the same as this:
def mult(x, y):
return x * y
mult = dec(mult)
In both cases I am replacing mult with whatever the function dec(mult) returns. The decorator syntax is just a convenience to express that. If dec doesn't return a function then I am going to get an error when I try to call mult.
>>> def dec(fn):
... return 12
...
>>> @dec
... def mult(x, y):
... return x * y
...
>>> mult
12
>>> mult(9, 5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not callable
>>>
mult is 12 so that last line is "12(9, 5)" and 12 is not a callable function, hence TypeError.
Upvotes: 2