I'm trying to write python decorator for memoize. I have few questions.
..
class memoize:
    def __init__(self):
        self.cache = {}
    def __call__(self, function):
        def wrapper(*args, **kwargs):
            key = str(function.__name__) + str(args) + str(kwargs)
            if key in cache:
                return cache[key]
            else:
                value = function(*args, **kwargs)
                cache[key] = value
                return value
        return wrapper
@memoize
def fib(n):
    if n in (0, 1):
        return 1
    else:
        return fib(n-1) + fib(n-2)
for i in range(0, 10):
    print(fib(i))
I'm getting compilation error.
Traceback (most recent call last):
  File "memoize.py", line 17, in <module>
    @memoize
TypeError: __init__() takes exactly 1 argument (2 given)
                @decorator is just a syntactic sugar for func = decorator(func). So here comes a difference:(1)
@decorator 
def func():
     ...
is same as
func = decorator(func)  # Just call of __init__
func(...)               # Call of decorator.__call__
but (2)
@decorator(some_param)
def func():
     ...
is similiar to
# Call of __init__ plus call of __call__
func = decorator(some_param)(func)  
# Call of closure returned by decorator.__call__
func(...)   
You have implemented decorator accepting arguments for (2) syntax, but do not provide them when using them as in example (1). That is why __init__ complaining, it receives func as second argument.
You should write self.cache in a wrapper closure, so wrapper would reference corresponding decorator object. Writing just cache will cause global variable search and thus will fail.
UPD: I changed your code to approach (1):
class memoize:
    def __init__(self, function):
        self.cache = {}
        self.function = function
    def __call__(self, *args, **kwargs):        
        key = str(args) + str(kwargs)
        if key in self.cache:
            return self.cache[key]
        value = self.function(*args, **kwargs)
        self.cache[key] = value
        return value
@memoize
def fib(n):
    if n in (0, 1):
        return 1
    else:
        return fib(n-1) + fib(n-2)
for i in range(0, 10):
    print(fib(i))
print(fib.cache)
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With