Python 将输入函数传递给多个类装饰器
我有一个计时器装饰器,在屏幕上打印一个记忆装饰功能所用的时间。但是,decorator print语句将memoize类打印为屏幕上的函数名,而不是要memoize的函数输入。例如,使用此代码:Python 将输入函数传递给多个类装饰器,python,python-2.7,decorator,python-decorators,memoization,Python,Python 2.7,Decorator,Python Decorators,Memoization,我有一个计时器装饰器,在屏幕上打印一个记忆装饰功能所用的时间。但是,decorator print语句将memoize类打印为屏幕上的函数名,而不是要memoize的函数输入。例如,使用此代码: from memoization import Memoize import time import logging from timer import Timer @Timer @Memoize def pass_and_square_time(seconds): time.s
from memoization import Memoize
import time
import logging
from timer import Timer
@Timer
@Memoize
def pass_and_square_time(seconds):
time.sleep(seconds)
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):
Timer Time Elapsed: 30.0 seconds
<memoization.Memoize object at 0x02E5BBD0> 30.0 seconds
The initial call of pass_and_square_time(30) yields: 900
Timer Time Elapsed: 0.0 seconds
<memoization.Memoize object at 0x02E5BBD0> 0.0 seconds
The second call of pass_and_square_time(30) yields: 900
我的Memoize类实现如下:
class Timer(object):
def __init__(self, fcn=None, timer_name='Timer'):
self._start_time = None
self._last_timer_result = None
self._display = 'seconds'
self._fcn = fcn
self._timer_name = timer_name
def __call__(self, *args):
self.start()
fcn_res = self._fcn(*args)
self.end()
print '\n\t{func} {time} seconds'.format(func=self._fcn, time=self.last_timer_result)
return fcn_res
def __get__(self, obj, objtype):
return partial(self.__call__, obj)
'''
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
'''
from functools import update_wrapper, partial
class Memoize(object):
def __init__(self, fcn):
self._fcn = fcn
self._memo = {}
update_wrapper(self, fcn)
def __call__(self, *args):
if args not in self._memo:
self._memo[args] = self._fcn(*args)
return self._memo[args]
def __get__(self, obj, objtype):
return partial(self.__call__, obj)
使用闭包比使用类简单得多
import functools
import time
def memoize(f):
_memo = {}
@functools.wraps(f)
def _(*args):
if args not in _memo:
_memo[args] = f(*args)
return _memo[args]
return _
我将类似地编写计时器
def timer(f):
@functools.wraps(f)
def _(*args):
start = time.time()
rv = f(*args)
end = time.time()
print '\n\t{func} {t} seconds'.format(func=f.__name__, t=end - start)
return rv
return _
然后
Timer
和Memoize
都是作为类实现的,它们在修饰函数时返回自己类的实例。因此,无法使用functools.wrap
或在返回的函数上设置\uuuu name\uuuu
(因为没有返回的函数)
相反,我建议在Timer
和Memoize
上实现,这将更好地表示修饰过的函数。当Python解释器需要获取对象的字符串表示形式时,它将调用该函数
这就是目前的情况和问题:
def pass_and_square_time(seconds):
time.sleep(seconds)
return seconds**2
print(pass_and_square_time) # <function pass_and_square_time at 0x00000000029A1620>
print(Memoize(pass_and_square_time)) # <Memoize object at 0x000000000295BDA0>
然后,它会按预期工作:
print(pass_and_square_time) # <function pass_and_square_time at 0x00000000029A1620>
print(Memoize(pass_and_square_time)) # <function pass_and_square_time at 0x00000000029A1620>
请注意,Timer(Memoize(传递时间和平方时间))
正是装饰者在这里所做的:
@Timer
@Memoize
def pass_and_square_time(seconds):
time.sleep(seconds)
return seconds**2
“我想要那
记忆化。记忆化
成为传递时间”
“这真的是你想要的吗?看起来很简单,但我不明白这有什么意义。我非常感谢你的帮助,如果我能记下2个正确答案,我会的,但我最终改变了备忘录,这样它就不是一门课了,因为我真的没有理由把它作为一门课。谢谢你@那很好。我很高兴你能接受这个答案。无论如何,正如您所写,您只能接受一个答案,但您可以对任意多个答案给出+1;)当我获得15个声誉时,我一定会回过头来,给两个都打+1。不幸的是,我现在处于10分以下@zvone@strwars啊,我明白了:)如果你碰巧知道关于多重处理的任何事情,我有一个完全不同的问题@zvone…:D
print(pass_and_square_time) # <function pass_and_square_time at 0x00000000029A1620>
print(Memoize(pass_and_square_time)) # <function pass_and_square_time at 0x00000000029A1620>
print(Timer(Memoize(pass_and_square_time))) # <function pass_and_square_time at 0x00000000029A1620>
@Timer
@Memoize
def pass_and_square_time(seconds):
time.sleep(seconds)
return seconds**2