我有以下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
以便可以Bar
从decorator
函数中访问该类(或其他任何类)?
我试过没有运气@classmethod
的deco_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] 删除。
我来说两句