Python-元类装饰器-如何使用@classmethod

大卫·卡兰南

我有以下Python元类,可deco_with_args为每个类添加装饰器:

def deco_with_args(baz):
    def decorator(func):
        ...
        return func
    return decorator

class Foo(type):
    def __prepare__(name, bases):    
        return {'deco_with_args': deco_with_args}

这使我可以像这样使用装饰器:

class Bar(metaclass=Foo):
    @deco_with_args('baz')
    def some_function(self):
        ...

如何使deco_with_args装饰器的行为类似于,@classmethod以便可以Bardecorator函数中访问该类(或其他任何类)

我试过没有运气@classmethoddeco_with_args功能。

布宜诺斯艾利斯

关于您的问题有两种解释-调用示例中cls命名的函数时是否需要可用decorator(即,需要修饰后的方法成为类方法),就可以将其本身转换为类方法:

def deco_with_args(baz):
    def decorator(func):
        ...
        return classmethod(func)
    return decorator

第二个是在类创建cls是否需要deco_with_args调用自身时,在创建修饰函数本身可用现在被列为已被接受的答案列出了一个直接的问题:在运行类主体时该类尚不存在,因此,无法在解析该类主体时获得具有以下方法的方法:知道班级本身。

但是,不同于该答案试图暗示的是,这不是真正的交易。您要做的就是cls在类创建过程结束时懒惰地运行装饰器代码(需要的代码)。您已经有一个元类设置,因此,只需在装饰代码周围添加另一个可调用层,就可以做到这一点很简单:

def deco_with_args(baz):
    def outter_decorator(func):
        def decorator(cls):
            # Code that needs cls at class creation time goes here
            ...

            return func
        return decorator
    outter_decorator._deco_with_args = True
    return outter_decorator

class Foo(type):
    def __prepare__(name, bases):    
        return {'deco_with_args': deco_with_args}

    def __init__(cls, cls_name, bases, namespace, **kwds):
        for name, method in cls.__dict__.items():
            if getattr(method, '_deco_with_args', False):
                cls.__dict__[name] = method(cls)

        super().__init__(cls_name, bases, namespace, **kwds)

当然,这将在类主体执行完成之后但在class运行之后的任何其他Python语句之前运行。如果您的装饰器会影响在类主体本身内部执行的其他元素,那么您所需要做的就是将它们包装起来以保证也可以进行延迟执行。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章