Python为静态方法编写装饰器

时间:2014-12-22 22:17:43

标签: python regex caching decorator static-methods

我正在尝试创建一个函数来缓存它的一些属性,因为这些函数需要一些计算才能返回结果。由于它是相同的结果,我想以某种方式缓存它,允许重用。

一些代码可以透视:

这就是我提出的装饰器的样子:

def cachedAttributes(func, **kwargs):
    func.__dict__.update(kwargs)
    return func

我想要装饰的类方法:

class someclass:
    @staticmethod
    def method(*args):
        # compile regex operation
        # compile regex operation
        # compile regex operation

        # compute and return something
        ...
        pass

这就是我使用装饰器的方式

class someclass:
    @staticmethod
    @cachedAttributes(method, doctyperegex = re.compile(r'<!DOCTYPE.*?>\s*', re.S|re.U),
                  htmlregex = re.compile(r'<html.*?>\s*', re.S|re.U),
                  metaregex = re.compile(r'<meta(.*?)>', re.S|re.U))
    def method(*args):
        # compile regex operation
        # compile regex operation
        # compile regex operation

        # compute and return something
        ...
        pass

所以上面是我正在使用的代表。我有一个类,它有一个静态方法,使用一些正则表达式对象进行一些计算,我想缓存compile regex操作的结果。但是,这给了我以下错误:

@staticmethod
NameError: name 'method' is not defined

我知道这是因为在尝试装饰之前没有定义方法,但我怎么能这样做呢?是否有内置可以为我做这个?

2 个答案:

答案 0 :(得分:1)

您需要遵循以下常见模式:您需要一个获取预期参数并返回装饰器函数的函数。

def cachedAttributes(**kwargs):
    def decorator(func):
        func.__dict__.update(kwargs)
        return func
    return decorator

然后:

class someclass:
    @staticmethod
    @cachedAttributes(doctyperegex = re.compile(r'<!DOCTYPE.*?>\s*', re.S|re.U),
              htmlregex = re.compile(r'<html.*?>\s*', re.S|re.U),
              metaregex = re.compile(r'<meta(.*?)>', re.S|re.U))
    def method(*args):
        # compile regex operation
        # compile regex operation
        # compile regex operation

        # compute and return something
        ...
        pass

答案 1 :(得分:1)

当Python应用装饰器时,你的装饰器将被传递method函数。你需要给你的装饰工厂提供方法作为参数:

@cachedAttributes(doctyperegex = re.compile(r'<!DOCTYPE.*?>\s*', re.S|re.U),
              htmlregex = re.compile(r'<html.*?>\s*', re.S|re.U),
              metaregex = re.compile(r'<meta(.*?)>', re.S|re.U))

你的cachedAttributes() callable然后返回实际的装饰器:

def cachedAttributes(**kwargs):
    def decorator(func):
        func.__dict__.update(kwargs)
        return func
    return decorator

所以Python调用cachedAttributes(),它返回一个装饰器。然后调用传入函数对象,返回值用作装饰函数的替换。这可能是原始的功能对象,就像你在这里一样。