如何在Python中使用自定义元类来装饰继承的方法?

问题描述 投票:0回答:1

我正在使用自定义元类来装饰类的方法。但是,它目前仅修饰直接在类中定义的方法,而不修饰从父类继承的方法。

我的课程结构如下:

class Abstract1(ABC):

class A(Abstract1):
   def fun1(self):
   def fun2(self):

class DecoMeta(ABCMeta):

class B(A, metaclass=DecoMeta):
   def hello(self):

我的 DecoMeta 类如下所示:

class DecoMeta(ABCMeta):
    """ Decorator class
    """
    def __new__(mcs, name: str, bases: tuple, attrs: dict):
        for attr_name, attr_value, in attrs.items():
            if isinstance(attr_value, types.FunctionType):
                attrs[attr_name] = mcs.deco(attr_value)

        return super(DecoMeta, mcs).__new__(mcs, name, bases, attrs)

    @classmethod
    def deco(mcs, func):
        """ Decorate func
        """
        async def wrapper(*args, **kwargs):
            result = await func(*args, **kwargs)
            # print(args[0].__dict__.keys())
            args[0].some_function(). # i.e. self.some_function()
            return result
        return wrapper

当我打印 args[0].dict.keys() 时,它只打印出类 B 中定义的函数。这意味着 decoMeta 只装饰这些函数(在本例中为 hello())。我想使用这个 DecoMeta 来装饰父类中定义的所有函数,即 A 类(如 fun1() 和 fun2())。有办法做到吗?

python decorator metaclass
1个回答
0
投票

您还必须将

A
注册到元类。

实现此目的的一种方法是将元类也传递给父类:

class Abstract1(ABC):
    pass

class DecoMeta(ABCMeta):
    pass

class A(Abstract1, metaclass=DecoMeta):
    def fun1(self):
        pass

    def fun2(self):
        pass

class B(A, metaclass=DecoMeta):
    def hello(self):
        pass

修改后的

DecoMeta
,只是为了显示
attr_name


class DecoMeta(ABCMeta):
    """ Decorator class
    """
    def __new__(mcs, name: str, bases: tuple, attrs: dict):
        for attr_name, attr_value, in attrs.items():
            if isinstance(attr_value, types.FunctionType):
                print(attr_name)
                # attrs[attr_name] = mcs.deco(attr_value)

        return super(DecoMeta, mcs).__new__(mcs, name, bases, attrs)

B()

输出

fun1
fun2
hello
© www.soinside.com 2019 - 2024. All rights reserved.