设置类变量的 Python 装饰器

izi*_*dor 4 python class decorator

我有一个代码,它获取所有函数的列表以及函数在FooBar其参数消息上支持的正则表达式:

functionList = []

def notify(RegExpression):
    def _notify(function):
        functionList.append((RegExpression, function))

        return function

    return _notify

class FooBar:
    @notify(".*")
    def everything(self, message):
        pass

        @notify("(\w+):.*")
    def reply(self, message):
        pass

for foo in functionList:
    print("%s => %s" % foo)
Run Code Online (Sandbox Code Playgroud)

我想做类似的事情,但将函数列表及其参数作为类变量放入类中。当FooBar存在更多类似的类时,它会防止出现问题。每个类都应该有自己的列表。

def notify(RegExpression):
    # ???

class FooBar:
    functionList = []

    @notify(".*")
    def everything(self, message):
        pass

        @notify("(\w+):.*")
    def reply(self, message):
        pass

for foo in FooBar.functionList:
    print("%s => %s" % foo)
Run Code Online (Sandbox Code Playgroud)

投入什么notify()

Sve*_*ach 5

直接使用函数装饰器执行此操作是不可能的,因为您需要访问当前正在定义的类,而该类尚不存在。一种解决方案是让装饰器只将正则表达式存储为方法的属性,并具有在基类上收集这些方法的功能:

def notify(regex):
    def decorate(func):
        func.regex = regex
        return func
    return decorate

class Baz(object):
    @property
    def function_list(self):
        for attr in dir(self):
            obj = getattr(self, attr)
            if callable(obj) and hasattr(obj, "regex"):
                yield obj

class FooBar(Baz):
    @notify(".*")
    def everything(self, message):
        pass

    @notify("(\w+):.*")
    def reply(self, message):
        pass

for foo in FooBar().function_list:
    print("%s => %s" % (foo.regex, foo))
Run Code Online (Sandbox Code Playgroud)