Python 2.7 Python2.7-使用类作为定时和记忆的装饰器

Python 2.7 Python2.7-使用类作为定时和记忆的装饰器,python-2.7,decorator,python-decorators,memoization,Python 2.7,Decorator,Python Decorators,Memoization,我是Python的新手,目前正在从事一个项目,我有一个Timer和Memoize类,这两个类都应该能够用作装饰器,并且可以使用具有任意数量参数的函数 问题 我目前的问题是,我试图将它们都用作函数的装饰器;但是,计时器仅在函数的第一次调用时调用,而不是在第二次调用时调用。例如,使用此代码: # Import the Memoize class from the memoization module from memoization import Memoize # Import the tim

我是Python的新手,目前正在从事一个项目,我有一个Timer和Memoize类,这两个类都应该能够用作装饰器,并且可以使用具有任意数量参数的函数

问题

我目前的问题是,我试图将它们都用作函数的装饰器;但是,计时器仅在函数的第一次调用时调用,而不是在第二次调用时调用。例如,使用此代码:

# Import the Memoize class from the memoization module
from memoization import Memoize


# Import the time module
import time


# Import the logging module
import logging


# Import the Timer class from the timer module
from timer import Timer


@Memoize
@Timer
def pass_and_square_time(seconds):
    # Call time.sleep(seconds)
    time.sleep(seconds)
    # Return the square of the input seconds amount.
    return seconds**2


def main():
    logging.getLogger().setLevel(logging.ERROR)

    print '\nFor pass_and_square_time({30}):'.format(n=num)
    print '\n\tThe initial call of pass_and_square_time(30) yields: {ret}'.format(ret=pass_and_square_time(30))
    print '\n\tThe second call of pass_and_square_time(30) yields: {ret}'.format(ret=pass_and_square_time(30))
返回以下内容:

For pass_and_square_time(30):

<function pass_and_square_time at 0x02B9A870> 30.003000021 seconds

    The initial call of pass_and_square_time(30) yields: 900

    The second call of pass_and_square_time(30) yields: 900

记忆化

我的Memoize类实现如下:

class Timer(object):
    def __init__(self, fcn, timer_name='Timer'):
        self._start_time = None
        self._last_timer_result = None
        self._display = 'seconds'
        self._fcn = fcn
        self._timer_name = timer_name
        self.__wrapped__ = self._fcn

    def __call__(self, *args):
        self.start()
        fcn_res = self._fcn(*args)
        self.end()
        print '\n{func} {time} seconds'.format(func=self._fcn, time=self.last_timer_result)
        return fcn_res

    '''
    start(), end(), and last_timer_result functions/properties implemented 
    below in order to set the start_time, set the end_time and calculate the 
    last_timer_result,  and return the last_timer_result. I can include more
    if you need it. I didn't include it just because I didn't want to make
    the post too long
    '''
class Memoize(object):
    def __init__(self, fcn):
        self._fcn = fcn
        self._memo = {}
    self.__wrapped__ = self.__call__

def __call__(self, *args):
    if args not in self._memo:
        self._memo[args] = self._fcn(*args)

    return self._memo[args]

使用的参考资料

我查看并试图对我的类进行建模的参考文献或是:

Python类装饰器

Python记忆化



感谢您的阅读和提供的任何帮助

对于代码,您正在记忆定时函数,这意味着在缓存中找到参数时也会跳过定时代码。如果你颠倒装饰者的顺序

@Timer
@Memoize
def pass_and_square_time(seconds):
    # Call time.sleep(seconds)
    time.sleep(seconds)
    # Return the square of the input seconds amount.
    return seconds**2

现在,您正在计时一个已记忆的函数。无论是否在缓存中找到参数,都可以为对Memoize函数的调用计时。

Memoize正在执行它应该执行的操作:它使用给定参数返回上一次调用的缓存值,而不是调用(计时)但是有没有一种方法可以让计时器被调用,无论memoize是否返回缓存的值,或者函数是否被调用@chepner?基本上,我想说明的是,memoize中的缓存值允许pass_和_square_time()函数在第二次调用时使用计时器装饰更快地返回值(如果有意义的话)。然后需要显式地对memoized函数计时,而不是对计时函数进行memoize。(这可能是一个简单的交换两个decorator的顺序;我还没有测试过。)交换两个decorator的顺序有效!!我以为我之前试过了,但没用,但我想我后来对代码的一次编辑可能已经修复了它。感谢您对愚蠢问题@chepnert的帮助交换装饰器的一个问题是计时器在其时间流逝打印语句中打印记忆函数名,而不是pass_和square_时间函数名。有没有关于如何解决这个问题的建议@chepner?再次感谢!查看
functools
模块;有一个decorator可以用来保存原始函数的元数据(
wrapps
wrapped
?)我尝试了wrapps,但我想我需要在memoize函数中返回一个wrapped函数,因为它是decorator@chepner。