使用元 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)
我正在尝试将所有方法包装在 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)