我一直在努力更好地理解装饰器和封闭装置。
我正在尝试修饰函数来实现:
我想使用两个单独的装饰器 - 用于科学:)
所以我设法创建了这个工作代码(我使用了一些代码片段 - 我承认)
class countcalls(object):
"Decorator that keeps track of the number of times a function is called."
__instances = {}
def __init__(self, f):
self.__f = f
self.__numcalls = 0
countcalls.__instances[f] = self
def __call__(self, *args, **kwargs):
self.__numcalls += 1
return self.__f(*args, **kwargs)
def count(self):
"Return the number of times the function f was called."
return countcalls.__instances[self.__f].__numcalls
@staticmethod
def counts():
"Return a dict of {function: # of calls} for all registered functions."
return dict([(f.__name__, countcalls.__instances[f].__numcalls) for f in countcalls.__instances])
def wrapper(x):
past=[]
@countcalls
def inner(y):
print x
print inner.count()
past.append(y)
print past
return inner
def main():
foo = wrapper("some constant")
foo(5)
foo("something")
if __name__ == '__main__':
main()
输出:
some constant
1
[5]
some constant
2
[5, 'something']
现在我想将memoize函数更改为一个整洁的pythonic装饰器。这是我到目前为止所提出的:
class countcalls(object):
"Decorator that keeps track of the number of times a function is called."
__instances = {}
def __init__(self, f):
self.__f = f
self.__numcalls = 0
countcalls.__instances[f] = self
def __call__(self, *args, **kwargs):
self.__numcalls += 1
return self.__f(*args, **kwargs)
def count(self):
"Return the number of times the function f was called."
return countcalls.__instances[self.__f].__numcalls
@staticmethod
def counts():
"Return a dict of {function: # of calls} for all registered functions."
return dict([(f.__name__, countcalls.__instances[f].__numcalls) for f in countcalls.__instances])
class memoize(object):
past=[]
def __init__(self, f):
past = []
self.__f = f
def __call__(self, *args, **kwargs):
self.past.append(*args)
return self.__f(*args, **kwargs)
def showPast(self):
print self.past
@memoize
@countcalls
def dosth(url):
print dosth._memoize__f.count() ## <-- this is so UGLY
dosth.showPast()
def main():
dosth("one")
dosth("two")
if __name__ == '__main__':
main()
这是输出:
1
['one']
2
['one', 'two']
如何摆脱丑陋的&#34; line(print dosth._memoize__f.count()
)?换句话说 - 如何直接调用堆叠装饰器的方法? (没有向装饰器添加一个方法来调用其他装饰器的方法 - 这不是我的观点)
答案 0 :(得分:0)
如果您想要访问特定的装饰器结果,您仍然需要打开装饰器,但是默认情况下&#39;这个属性是__wrapped__
。 {3}的Python 3版本为您设置了此属性(通过@functools.wraps()
decorator,从Python 3.4开始),但您可以在自己的装饰器中手动执行相同的操作:
class memoize(object):
past=[]
def __init__(self, f):
past = []
self.__wrapped__ = self.__f = f
现在您可以使用以下命令访问包装的可调用对象:
dosth.__wrapper__.count()
是标准的 Pythonic解包装饰器的方式。