使用元 class 包装所有 class 方法

Wrap all class methods using a meta class

我正在尝试将所有方法包装在 class 我用特定包装方法编写的文件中。

我的class继承自pythondictclass,我想包装此父级 class 的所有方法,例如 __setitem__、__getitem__ 等。

为了实现这一目标,我编写了一个元 class,它使用 [=51 将所有方法包装在其子 class 中=] 元 class 中的方法,所以我可以访问子 class 的对象(而不是 class 定义不包括父方法)。

但是,在 运行 代码之后,我发现从未调用包装器方法。意味着包装没有成功。

你能帮忙找出问题所在吗?

我的代码:

def wrapper(func):
    def wrapped(self, *args, **kwargs):
        print 'wrapper.__call__()'
        res = func(self, *args, **kwargs)
        return res
    return wrapped

class MyMeta(type):   
    def __init__(cls, classname, bases, class_dict):
        print 'meta.__init__()'
        new_class_dict = {}
        for attr_name in dir(cls):
            attr = getattr(cls, attr_name)
            if hasattr(attr, '__call__'):
                attr = wrapper(attr)
            new_class_dict[attr_name] = attr
        return super(MyMeta, cls).__init__(classname, bases, new_class_dict)

class MyDict(dict):

    __metaclass__ = MyMeta

    def __init__(self, *args):
        print 'child.__init__()'
        super(MyDict, self).__init__(*args)     

d = MyDict({'key': 'value'})
d['new_key'] = 'new_value'

我得到的打印输出是:

meta.__init__()
child.__init__()

没有任何参考 wrapper.__call__() 打印我放在包装方法中...

当调用元类 __init__ 时,class 对象已经构建,因此在此阶段修改属性字典(class_dict 在您的代码中)确实完全没有用。您想使用 setattr 代替:

class MyMeta(type):   
    def __init__(cls, classname, bases, class_dict):
        for attr_name in dir(cls):
            if attr_name == "__class__":
                # the metaclass is a callable attribute too, 
                # but we want to leave this one alone
                continue
            attr = getattr(cls, attr_name)
            if hasattr(attr, '__call__'):
                attr = wrapper(attr)
                setattr(cls, attr_name, attr)

        # not need for the `return` here
        super(MyMeta, cls).__init__(classname, bases, class_dict)