Reputation: 1
Example: Fibonaci recursive function with memoize decorator. When calling function helper there is no argument. If function helper is defined to take an argument x therefore i expect calling the function with one argument. I would like to understand why is syntax like it is?
def memoize(f):
memo = {}
def helper(x):
if x not in memo:
memo[x] = f(x)
return memo[x]
return helper
@memoize
def fib(n):
if n == 0:
return 0
elif n == 1:
return 1
else:
return fib(n-1) + fib(n-2)
print(fib(40))
Upvotes: 0
Views: 60
Reputation: 50210
I believe the syntax is like this so that it looks as streamlined as possible. You put a decorator object after the @
(a function that takes one argument, and returns a function), and python calls it with the function you are defining. This
@memoize
def fib(n):
...
Is exactly equivalent to the following, which doesn't use the magic decorator syntax:
def fib(n):
...
fib = memoize(fib)
If you want your head to spin a little, consider that @
can actually be followed by a function call -- but this function call must return a decorator that works as above! Here's a silly example that counts how many times the decorated function is called, but lets you set the start value. (It's just an example: it's not very useful since only one function can be decorated, etc.)
def countcalls(start):
global _calls
_calls = start
def decorator(f):
def wrapper(x):
global _calls
_calls += 1
return f(x)
return wrapper
return decorator
@countcalls(3)
def say(s):
print(s)
say("hello")
# _calls is now 4
Here, countcalls(4)
defines and returns (without calling it) the function decorator
, which will wrap the decorated function and return the wrapper in place of the function I wrote.
Upvotes: 0
Reputation: 10503
You do call the helper with the argument. Decorators are syntactic sugar for this
def fib(n):
if n == 0:
return 0
elif n == 1:
return 1
else:
return fib(n-1) + fib(n-2)
fib = memoize(fib)
So your fib
function is no longer the original fib
-function. It is in fact the helper
closure, because that's what memoize
returns – a closure. So, when you call fib(40)
you kind of call helper(40)
. The memoize
decorator creates a function object, it doesn't call it, just returns it.
Upvotes: 2