I have been testing out this caching method/code: http://code.activestate.com/recipes/498245-lru-and-lfu-cache-decorators/?c=15348
and in some cases, I get this (or similar) error: "AttributeError: 'str' object has no attribute 'module'"
and here are code examples, these work fine:
if __name__ == '__main__':
@lru_cacheItem(maxsize=20)
def f(x, y):
return 3*x+y
domain = range(5)
from random import choice
for i in range(1000):
r = f(choice(domain), choice(domain))
print('Hits:{0}'.format(f.hits), 'Misses:{0}'.format(f.misses))
@lfu_cacheItem(maxsize=20)
def f(x, y):
return 3*x+y
domain = range(5)
from random import choice
for i in range(1000):
r = f(choice(domain), choice(domain))
print('Hits:{0}'.format(f.hits), 'Misses:{0}'.format(f.misses))
@lru_cacheItem(maxsize=20)
def myString(a, b):
return '{0} and {1}'.format(a, b)
a = 'crap'
b = 'shit'
for i in range(1000):
r = myString(a, b)
print('Hits:{0}'.format(myString.hits), 'Misses:{0}'.format(myString.misses))
and this does not:
if __name__ == '__main__':
class P4client(object):
def __init__(self):
pass
def checkFileStats(self, filePath):
results = 'The filepath: {0}'.format(filePath)
print results
return results
p4client = P4client()
filePath = (r"C:\depot\tester.tga")
@lfu_cacheItem
def p4checkFileStats(filePath):
'''Will cache the fstats return'''
p4checkResults = p4client.checkFileStats(filePath)
return p4checkResults
p4checkFileStats(filePath)
I am not sure how to fix this ... it appears to be an issue in functools, I assume somehow do to that fact I am calling a class/method within the function I am wrapping?
@lfu_cacheItem
def p4checkFileStats(filePath):
You are missing parenthesis here:
@lfu_cacheItem()
def p4checkFileStats(filePath):
All decorators which expect "options", i.e. that you can use as:
@decorator(a=Something, b=Other, ...)
def the_function(...):
Must always be called when decorating, even if you do not provide arguments:
@decorator()
def the_function(...):
Why you wonder? Well, first of all remember that decorators are normal functions that accept a function as argument:
In [1]: def hooray(func):
...: print("I'm decorating function: {.__name__}".format(func))
...: return func
In [2]: @hooray
...: def my_function(): pass
I'm decorating function: my_function
As you can see hooray
was called. In fact this is what really happens when using a decorator:
In [3]: def my_function(): pass
...: my_function = hooray(my_function)
...:
I'm decorating function: my_function
Now, if you want to pass options to the decorator you can create a function that returns a decorator. This is exactly what happens with lfu_cache
from the recipe you link:
def lfu_cache(maxsize=100):
# ...
def decorating_function(user_function):
# ...
return decorating_function
Now here you can see that lfu_cache
is really a function. this function creates a decorator, called decorating_function
and returns it. This means that when calling:
@lfu_cache(maxsize=20)
def my_function(): pass
This is what happens:
def my_function(): pass
decorator = lfu_cache(maxsize=20)
my_function = decorator(my_function)
As you can see first lfu_cache
is called, and returns a decorator. Afterwards the decorator is called to decorate the function.
What happens if you forget the parenthesis? What does this:
@lfu_cache
def my_function(): pass
do?
Pretty simple, it uses lfu_cache
as a simple decorator:
def my_function(): pass
my_function = lfu_cache(my_function)
But this is bad! You passed a function as maxsize
parameter and the value returned by lfu_cache
is the decorating_function
of before!
to learn more about decorators read this So answer.
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