【发布时间】:2019-01-24 21:54:48
【问题描述】:
我是 Python 的新手,我目前正在做一个项目,我有一个 Timer 和 Memoize 类,它们都应该能够用作装饰器,并且可以使用具有任意数量参数的函数.
问题
我目前的问题是我试图将它们都用作函数的装饰器;但是,Timer 仅在第一次调用函数时调用,而不是第二次调用。例如,使用以下代码:
# 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 装饰器在第二次调用时工作正常,因为它最初在第一次调用之后出现,而不是执行 time.sleep(30) 调用。
定时器
我的 Timer 类实现如下:
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
'''
记忆
我的 Memoize 类实现如下:
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 类装饰器
- https://krzysztofzuraw.com/blog/2016/python-class-decorators.html
- Using classes as method decorators
- Python decorator best practice, using a class vs a function
Python 记忆
感谢您的阅读和您能提供的任何帮助!
【问题讨论】:
-
Memoize 正在做它应该做的事情:它使用给定的参数返回上次调用的缓存值,而不是再次调用(定时)函数。
-
但是有没有一种方法可以让我调用计时器,无论 memoize 返回缓存值还是调用函数 @chepner ?基本上,我想表明 memoize 中的缓存值允许 pass_and_square_time() 函数在第二次调用时使用 Timer 装饰更快地返回值,如果这有意义的话。
-
那么你需要显式地对记忆函数计时,而不是记忆一个计时函数。 (这可能很简单,就像交换两个装饰器的顺序一样;我还没有测试过。)
-
交换两个装饰器的顺序有效!!我以为我之前尝试过但无济于事,但我想我后来对代码的编辑之一可能已经修复了它。感谢@chepner 对愚蠢问题的帮助
标签: python-2.7 decorator python-decorators memoization