Python 将元类添加到库类
在我正在使用的Python库中,我想包装库中类的公共方法。我正在尝试使用元类来这样做Python 将元类添加到库类,python,metaprogramming,Python,Metaprogramming,在我正在使用的Python库中,我想包装库中类的公共方法。我正在尝试使用元类来这样做 from functools import wraps from types import FunctionType from six import with_metaclass def wrapper(func): @wraps(func) def wrapped(*args, **kwargs): print("wrapped %s" % func) ret
from functools import wraps
from types import FunctionType
from six import with_metaclass
def wrapper(func):
@wraps(func)
def wrapped(*args, **kwargs):
print("wrapped %s" % func)
return func(*args, **kwargs)
return wrapped
class MetaClass(type):
def __new__(mcs, classname, bases, class_dict):
library_class_dict = bases[0].__dict__
print(library_class_dict)
for attributeName, attribute in library_class_dict.items():
if type(attribute) == FunctionType and \
not attributeName.startswith('_'):
print("%s %s" % (attributeName, attribute))
attribute = wrapper(attribute)
library_class_dict[attributeName] = attribute
print(library_class_dict)
return type.__new__(mcs, classname, bases, class_dict)
# this is the class from the library that I cannot edit
class LibraryClass(object):
def library_method(self):
print("library method")
class Session(with_metaclass(MetaClass, LibraryClass)):
def __init__(self, profile, **kwargs):
super(Session, self).__init__(**kwargs)
self.profile = profile
当您将其放入Python文件并运行它时,会出现错误
TypeError: Error when calling the metaclass bases
'dictproxy' object does not support item assignment
我明白,试图直接分配给\uuu dict\uuu
是个坏主意。那不是我想做的。我更愿意将元类添加到LibraryClass,但我不确定如何添加
我已经讨论了关于Python元类编程的其他StackOverflow问题,但没有遇到任何试图将元类添加到库类的问题,因为在库类中,您无法获取源代码。您无法分配给代理。使用
setattr()
设置类的属性:
setattr(bases[0], attributeName, attribute)
然而,你不需要一个元类来做这件事,这在这里是完全过分的。您可以在该基类上执行此操作,并执行一次:
for attributeName, attribute in vars(LibraryClass).items():
if isinstance(attribute, FunctionType) and not attributeName.startswith('_'):
setattr(LibraryClass, attributeName, wrapper(attribute))
这只需执行一次,而不是每次创建
LibraryClass的子类时都执行一次,基本上您希望执行此操作:
LibraryClass.library_method = wrapper(LibraryClass.library_method)
对于所有方法,将自动执行
使用您的代码片段:
from functools import wraps
from types import FunctionType
class LibraryClass(object):
def library_method(self):
print("library method")
def wrapper(func):
@wraps(func)
def wrapped(*args, **kwargs):
print("wrapped %s" % func)
return func(*args, **kwargs)
return wrapped
您可以为所有方法编写一个帮助器函数:
def wrap_all_methods(cls):
for name, obj in cls.__dict__.items():
if isinstance(obj, FunctionType) and not name.startswith('_'):
setattr(cls, name, wrapper(obj))
return cls
LibraryClass = wrap_all_methods(LibraryClass)
现在,包装所有方法:
def wrap_all_methods(cls):
for name, obj in cls.__dict__.items():
if isinstance(obj, FunctionType) and not name.startswith('_'):
setattr(cls, name, wrapper(obj))
return cls
LibraryClass = wrap_all_methods(LibraryClass)
测试它是否工作:
class Session(LibraryClass):
pass
s = Session()
s.library_method()
印刷品:
wrapped <function LibraryClass.library_method at 0x109d67ea0>
library method
wrapped
库方法
方法已包装。如果我对您尝试执行的操作的理解是正确的,我认为类装饰器将更适合完成此任务,并且不太复杂。你给他们打过一针吗。你到底想达到什么目的。2.什么是完整的错误回溯?是否相关?library\u class\u dict
是对类dictproxy
对象的引用,不支持赋值。为什么要尝试从元类更改基类?为什么不在调用它们的super()
方法的新类中添加重写呢?@Pynchia:好吧,每次创建子类时都尝试更改基类(LibraryClass
)。。冗余的您只需要修改该基类一次,并且不需要为此使用元类。但是你能更准确地描述一下代码应该放在哪里吗?感谢you@Pynchia:任何你喜欢的地方,但在你需要使用任何包装方法之前,请确保它已运行。对我有用。与使用元类相比,代码要少得多。