微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

正则表达式匹配类方法的动态装饰器

如何解决正则表达式匹配类方法的动态装饰器

我想在委托类实现等情况下简化方法修饰。

  • 假设第 3 方“服务”类具有十分之一的方法
  • 你想覆盖大量的方法只是为了能够装饰它们
  • 您创建一个委托子类并覆盖选定的方法

这种情况会导致类似:

class ServiceDelegate(Service):
    @decorator
    def service_method1(self):
        super().service_method1()

    @decorator
    def service_method2(self):
        super().service_method2()

    @decorator
    def service_method3(self):
        super().service_method3()

    ...

这个解决方案似乎不太有效。出于这个原因,可以实现这样的事情:

def methods_decorator(deco,regex: str,base_class=None):
    def f(c: type):
        nonlocal base_class
        # Default base class is the decorated class itself
        if not base_class:
            base_class = c
        avoid_functions: List[str] = ["__init__","__doc__","__module__"]
        # regex functions
        def lmd(i): return i[0] not in avoid_functions and re.fullmatch(regex,i[0])
        funcs = list(filter(lmd,base_class.__dict__.items()))

        for func in funcs:
            print(str(type(func[1])))
            if type(func[1]) == FunctionType:
                setattr(c,func[0],deco(func[1]))
            elif type(func[1]) == StaticmethodType:
                setattr(c,staticmethod(deco(func[1])))
            elif type(func[1]) == ClassMethodType:
                setattr(c,classmethod(deco(func[1])))
        return c
    return f


@methods_decorator(deco=decorator1,regex="service_method.*",base_class=Service)
@methods_decorator(deco=decorator2,regex="other_method.*",base_class=Service)
@methods_decorator(deco=decorator3,regex="new.*")
class ServiceDelegate(Service): 
    def new_method(self):
        # Some new func here
    ...

这个想法是从基类“复制”和装饰正则表达式选择的函数,而不必覆盖它们。这个实现适用于我的特定场景。

我对 python 还很陌生,所以我不确定这是一个方法还是一个不好的做法。

  • 是否有任何理由不应用这种解决方
  • 是否有现有的 Python 包提供类似的功能

解决方法

解决方案是减少输入。然而,它只是将复杂性从添加方法装饰器转移到命名方法和添加魔法类装饰器。

更改方法装饰器的名称和方法名称是更好的主意。

class ServiceDelegate(Service):
    @service
    def method1(self):
        super().method1()

    @service
    def method2(self):
        super().method2()

    @service
    def method3(self):
        super().method3()

省略 service_ 前缀并添加 @service 完全不会改变键入的字符数量,并且不再需要魔法类装饰器。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。