【发布时间】:2017-09-08 22:41:52
【问题描述】:
我有这门课:
class SomeClass(object):
def __init__(self):
self.cache = {}
def check_cache(method):
def wrapper(self):
if method.__name__ in self.cache:
print('Got it from the cache!')
return self.cache[method.__name__]
print('Got it from the api!')
self.cache[method.__name__] = method(self)
return self.cache[method.__name__]
return wrapper
@check_cache
def expensive_operation(self):
return get_data_from_api()
def get_data_from_api():
"This would call the api."
return 'lots of data'
这个想法是,如果结果已经被缓存,我可以使用@check_cache 装饰器来防止expensive_operation 方法再次调用 api。
这似乎很好。
>>> sc.expensive_operation()
Got it from the api!
'lots of data'
>>> sc.expensive_operation()
Got it from the cache!
'lots of data'
但我希望能够使用另一个装饰器对其进行测试:
import unittest
class SomeClassTester(SomeClass):
def counted(f):
def wrapped(self, *args, **kwargs):
wrapped.calls += 1
return f(self, *args, **kwargs)
wrapped.calls = 0
return wrapped
@counted
def expensive_operation(self):
return super().expensive_operation()
class TestSomeClass(unittest.TestCase):
def test_api_is_only_called_once(self):
sc = SomeClassTester()
sc.expensive_operation()
self.assertEqual(sc.expensive_operation.calls, 1) # is 1
sc.expensive_operation()
self.assertEqual(sc.expensive_operation.calls, 1) # but this goes to 2
unittest.main()
问题在于counted装饰器计算的是wrapper函数被调用的次数,而不是这个内部函数。
我如何从SomeClassTester 计算?
【问题讨论】:
-
这对我有用 (AssertionError: 2 != 1) 吗?或者你想那样,你想数一下,你已经装饰了两次的原始昂贵操作?
-
我希望第二个断言为 1,因为该方法不会被第二次调用,而是会返回缓存调用的值。
标签: python python-3.x python-decorators