我正在尝试构建我的第一个装饰器并在类中实现它。
while ($myrow = mysqli_fetch_array($result)):
$username = $myrow["username"];
$date = $myrow["date"];
$returned = $myrow["returned"];
$color;
$formattedDate = date("d-m-Y", strtotime($myrow["date"]));
$table = '<tr>';
if ($returned == 'Yes'){
$color = "green";
} else if ($date < date("Y-m-d")) {
$color = "red";
} else{
$color = "blue";
}
$table.= '<td><div style="color: '.$color.';">'.$username.'</div></td>';
$table.= '<td><div style="color: '.$color.';">'.$formattedDate.'</div></td>'
$table.= '<td><div style="color: '.$color.';">'.$returned.'</div></td>';
$table .= '<tr>';
echo $table;
endwhile;
我正在尝试在下面的类中调用装饰器:
# 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()
我接近完成这项工作。我做错了什么?
答案 0 :(得分:1)
您需要从__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
答案 1 :(得分:1)
如果你忘记@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 wrapper