thadeusb / flask-cache

Cache extension for Flask
http://packages.python.org/Flask-Cache/
Other
697 stars 185 forks source link

memoize decorator behaving differently from typical decorator when instantiated without syntactic sugar #120

Closed gene1wood closed 8 years ago

gene1wood commented 9 years ago

First, this is most likely due to my own misunderstanding of how memoize is used and hence the best thing to come out of this issue might be a documentation change.

When using the memoize decorator with the @ symbol syntactic sugar described in the memoize documentation everything works as described.

When I manually instantiate memoize without the @ symbol, I get the error memoize() takes exactly 1 argument

Here is a code block that illustrates the differing behavior with memoize and compares it to a typical decorator (in this case the one used in wikipedia to illustrate decorators)

Using memoize as described in the documentation

import random, traceback
from flask import Flask
from flask.ext.cache import Cache
app = Flask(__name__)
cache = Cache(app,config={'CACHE_TYPE': 'simple'})

print "Using memoize as described in the documentation"

@cache.memoize(timeout=50)
def big_foo(a, b):
    return a + b + random.randrange(0, 1000)

print "big_foo(1,2) %s" % big_foo(1,2)
print "big_foo(3,4) %s" % big_foo(3,4)
print "big_foo(1,2) %s" % big_foo(1,2)

Using memoize without the syntactic sugar

print "Using memoize without the syntactic sugar"

def big_bar(a, b):
    return a + b + random.randrange(0, 1000)

big_bar = cache.memoize(big_bar)

try:
    print "big_bar(1,2) %s" % big_bar(1,2)
except Exception, err:
    print(traceback.format_exc())

Using a typical decorator with syntactic sugar

print "Using a typical decorator with syntactic sugar"
# https://en.wikipedia.org/wiki/Python_syntax_and_semantics#Decorators

def viking_chorus(myfunc):
    def inner_func(*args, **kwargs):
        for i in range(8):
            myfunc(*args, **kwargs)
    return inner_func

@viking_chorus
def menu_item():
    print("spam")

print "menu_item() %s" % menu_item()

Using a typical decorator without syntactic sugar

print "Using a typical decorator without syntactic sugar"

def menu_item_alternate():
    print("egg")

menu_item_alternate = viking_chorus(menu_item_alternate)

print "menu_item_alternate() %s" % menu_item_alternate()
jonafato commented 9 years ago

This is breaking because the functions are not being called in the same way. If you change your "without syntactic sugar" invocation from

big_bar = cache.memoize(big_bar)

to

big_bar = cache.memoize(timeout=50)(big_bar)

you should see identical behavior.