我正在尝试将所有方法包装在用特定包装方法编写的类中。
我的类继承自python dict 类,并且我想包装该父类的所有方法,例如 __ setitem__, __getitem __ 等
为了实现这一目标,我编写了一个元类,该元类使用元类中的 __ init __ 方法将所有方法包装在其子类中,因此我可以访问子类的对象(而不是不包含父方法的类定义)。
但是,在运行代码之后,我看到从未调用wrapper方法。意味着包装没有成功。
您能帮忙弄清楚哪里出了问题吗?
我的代码:
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 __()印刷品,而是将其放置在包装好的方法中...
答案 0 :(得分:1)
调用元类__init__
时,已经建立了class
对象,因此在此阶段修改属性dict(代码中的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)