2013-08-28 7 views
2

Я тестировал этот метод кэширования/код: http://code.activestate.com/recipes/498245-lru-and-lfu-cache-decorators/?c=15348AttributeError: «ул» объект не имеет атрибута «__module__»

, а в некоторых случаях, я получаю эту (или подобную) ошибку: «AttributeError: «ул» объект не имеет атрибута «модуль»»

и вот примеры кода, они работают отлично:

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)) 

и это не делает:

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) 

Я не уверен, как это исправить ... это, кажется, проблема в functools, я предполагаю, что-то делать с тем фактом, я звоню класс/метод в функции Я оберточной?

ответ

5
@lfu_cacheItem    
def p4checkFileStats(filePath): 

Вы отсутствуют круглые скобки здесь:

@lfu_cacheItem()    
def p4checkFileStats(filePath): 

Все декораторы, которые ожидают "варианты", то есть, что вы можете использовать как:

@decorator(a=Something, b=Other, ...) 
def the_function(...): 

Должен всегда называется при оформлении, даже если вы не указали аргументы:

@decorator() 
def the_function(...): 

Почему вы задаетесь вопросом? Ну, прежде всего, помните, что декораторы нормальные функции, которые принимают функции в качестве аргумента:

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 

Как вы можете видеть hooray был называется. На самом деле это то, что на самом деле происходит при использовании декоратора:

In [3]: def my_function(): pass 
    ...: my_function = hooray(my_function) 
    ...: 
I'm decorating function: my_function 

Теперь, если вы хотите передать параметры декоратора вы можете создать функцию, которая возвращает декоратора. Это именно то, что происходит с lfu_cache из рецепта вам ссылка:

def lfu_cache(maxsize=100): 
    # ... 
    def decorating_function(user_function): 
     # ... 
    return decorating_function 

Теперь здесь вы можете увидеть, что lfu_cache действительно функция. эта функция создает декоратор, который называется decorating_function и возвращает его. Это означает, что при вызове:

@lfu_cache(maxsize=20) 
def my_function(): pass 

Это то, что происходит:

def my_function(): pass 
decorator = lfu_cache(maxsize=20) 
my_function = decorator(my_function) 

Как вы можете видеть первый lfu_cache называется, и возвращает декоратора. Впоследствии декоратор призван украсить функцию. Что произойдет, если вы забудете скобки? Что это:

@lfu_cache 
def my_function(): pass 

do?

Довольно простой, он использует lfu_cache как простой декоратор:

def my_function(): pass 
my_function = lfu_cache(my_function) 

Но это плохо! Вы передали функцию как параметр maxsize, а значение, возвращаемое lfu_cache, - это decorating_function of before!

Чтобы узнать больше о декораторах, прочитайте this Так что ответьте.