首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从类到装饰器的python3自变量

从类到装饰器的python3自变量
EN

Stack Overflow用户
提问于 2017-05-23 14:28:00
回答 2查看 80关注 0票数 2

我正在尝试构建我的第一个装饰器并在一个类中实现它。

代码语言:javascript
复制
# 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

我正在给下课的装修师打电话:

代码语言:javascript
复制
class Zabb(object):

  @Cache('nodes.json',minutes=1)
  def getNodes(self):
    return "Get Nodes"

我这样叫它:

代码语言:javascript
复制
z = Zabb()
nodes = z.getNodes()

我得到以下错误:

代码语言:javascript
复制
Traceback (most recent call last):
File "./deco.py", line 52, in <module>
nodes = z.getNodes()
TypeError: 'str' object is not callable

我差一点就能成功了。我做错了什么?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-05-23 14:51:16

您需要从__call__方法返回一个高阶函数(包装)。添加一个内部方法并返回它。

代码语言:javascript
复制
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
EN

Stack Overflow用户

发布于 2017-05-23 14:53:17

如果您忘记了@deco的语法糖和它真正做什么的原因,那么装饰师就更容易理解。在你的例子中,

代码语言:javascript
复制
@Cache('nodes.json',minutes=1)
def getNodes(self):
    return "Get Nodes"

真正的意思是:

代码语言:javascript
复制
def getNodes(self):
    return "Get Nodes"

getNodes = Cache('nodes.json',minutes=1)(getNodes)

它实际上将Zabb.getNodes重新绑定到Cache('nodes.json',minutes=1).__call__(getNodes)的结果--这是一个字符串,而不是函数。

您想要的是使Cache.__call__返回一个函数,该函数将封装调用修饰的函数,即:

代码语言:javascript
复制
  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
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44137608

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档