我正在尝试构建我的第一个装饰器并在一个类中实现它。
# decorator class
class Cache(object):
def __init__(self,filename,**kwargs):
self.time_ago = datetime.now() - timedelta(**kwargs)
self.filename = filename
def __call__(self,fn):
if not os.path.isfile(self.filename):
return self.cache(fn(self))
time_ago = self.time_ago
filename = self.filename
c_age = datetime.fromtimestamp(os.path.getctime(filename))
m_age = datetime.fromtimestamp(os.path.getmtime(filename))
print (c_age)
print (m_age)
print (time_ago)
if c_age < time_ago or m_age < time_ago:
return self.cache(fn(self))
else:
return self.read()
def cache(self,data):
with open(self.filename,'r+') as ef:
ef.write(data)
return ef.read()
def read(self):
f = open(self.filename,'r')
data = f.read()
f.close()
return data我正在给下课的装修师打电话:
class Zabb(object):
@Cache('nodes.json',minutes=1)
def getNodes(self):
return "Get Nodes"我这样叫它:
z = Zabb()
nodes = z.getNodes()我得到以下错误:
Traceback (most recent call last):
File "./deco.py", line 52, in <module>
nodes = z.getNodes()
TypeError: 'str' object is not callable我差一点就能成功了。我做错了什么?
发布于 2017-05-23 14:51:16
您需要从__call__方法返回一个高阶函数(包装)。添加一个内部方法并返回它。
def __call__(self, fn):
def wrapper(*args, **kwargs): # <-- Add this wrapper
if not os.path.isfile(self.filename):
return self.cache(fn(*args, **kwargs))
time_ago = self.time_ago
filename = self.filename
c_age = datetime.fromtimestamp(os.path.getctime(filename))
m_age = datetime.fromtimestamp(os.path.getmtime(filename))
print (c_age)
print (m_age)
print (time_ago)
if c_age < time_ago or m_age < time_ago:
return self.cache(fn(*args, **kwargs))
else:
return self.read()
return wrapper # <-- Return the wrapper发布于 2017-05-23 14:53:17
如果您忘记了@deco的语法糖和它真正做什么的原因,那么装饰师就更容易理解。在你的例子中,
@Cache('nodes.json',minutes=1)
def getNodes(self):
return "Get Nodes"真正的意思是:
def getNodes(self):
return "Get Nodes"
getNodes = Cache('nodes.json',minutes=1)(getNodes)它实际上将Zabb.getNodes重新绑定到Cache('nodes.json',minutes=1).__call__(getNodes)的结果--这是一个字符串,而不是函数。
您想要的是使Cache.__call__返回一个函数,该函数将封装调用修饰的函数,即:
def __call__(self,fn):
def wrapper(*args, **kw):
if not os.path.isfile(self.filename):
return self.cache(fn(self))
time_ago = self.time_ago
filename = self.filename
c_age = datetime.fromtimestamp(os.path.getctime(filename))
m_age = datetime.fromtimestamp(os.path.getmtime(filename))
print (c_age)
print (m_age)
print (time_ago)
if c_age < time_ago or m_age < time_ago:
return self.cache(fn(self))
else:
return self.read()
return wrapperhttps://stackoverflow.com/questions/44137608
复制相似问题