用 Python 完全包装一个对象 [英] Completely wrap an object in Python
问题描述
我想完全包装一个对象,以便所有属性和方法请求都转发到它包装的对象,但也覆盖我想要的任何方法或变量,以及提供一些我自己的方法.这个包装类应该 100% 显示为现有类(isinstance
必须表现得好像它实际上是类),但是子类化本身并不会削减它,因为我想包装一个现有的 对象.Python中是否有一些解决方案可以做到这一点?我在想一些事情:
I am wanting to completely wrap an object so that all attribute and method requests get forwarded to the object it's wrapping, but also overriding any methods or variables that I want, as well as providing some of my own methods. This wrapper class should appear 100% as the existing class (isinstance
must act as if it is actually the class), however subclassing in itself is not going to cut it, as I want to wrap an existing object. Is there some solution in Python to do this? I was thinking something along the lines of:
class ObjectWrapper(BaseClass):
def __init__(self, baseObject):
self.baseObject = baseObject
def overriddenMethod(self):
...
def myOwnMethod1(self):
...
...
def __getattr__(self, attr):
if attr in ['overriddenMethod', 'myOwnMethod1', 'myOwnMethod2', ...]
# return the requested method
else:
return getattr(self.baseObject, attr)
但我对覆盖 __getattr__
、__setattr__
和 __hasattr__
不太熟悉,所以我不确定如何正确使用.
But I'm not that familiar with overriding __getattr__
, __setattr__
and __hasattr__
, so I'm not sure how to get that right.
推荐答案
大多数情况下最简单的方法可能是:
The simplest way in most cases is probably:
class ObjectWrapper(BaseClass):
def __init__(self, baseObject):
self.__class__ = type(baseObject.__class__.__name__,
(self.__class__, baseObject.__class__),
{})
self.__dict__ = baseObject.__dict__
def overriddenMethod(self):
...
以这种方式工作,即通过以这种方式重新分配 self 的 __class__
和 __dict__
,您只需要提供您的覆盖——Python 的正常属性获取和设置机制就可以了其余的……大部分.
Working in this way, i.e. by reassigning self's __class__
and __dict__
in this fashion, you need only provide your overrides -- Python's normal attribute getting and setting mechanisms will do the rest... mostly.
只有在 baseObject.__class__
定义了 __slots__
时,您才会遇到麻烦,在这种情况下,多重继承方法不起作用,您确实需要繁琐的 __getattr__
(正如其他人所说,至少你不必担心它会被你覆盖的属性调用,因为它不会!-),__setattr__
(更大的痛苦,因为它确实被每个属性调用)等;而让isinstance
和特殊方法工作起来,需要费心费力的细致工作.
You'll be in trouble only if baseObject.__class__
defines __slots__
, in which case the multiple inheritance approach doesn't work and you do need the cumbersome __getattr__
(as others said, at least you don't need to worry that it will be called with attributes you're overriding, as it won't!-), __setattr__
(a greater pain, as it DOES get called for every attribute), etc; and making isinstance
and special methods work takes painstaking and cumbersome detailed work.
本质上,__slots__
意味着一个类是一个特殊的,每个实例都是一个轻量级的值对象",不会受到进一步复杂的操作、包装等的影响,因为需要节省几个字节该类的每个实例都会覆盖所有关于灵活性等的正常问题;因此,以与处理 99% 以上的 Python 对象相同的流畅和灵活的方式处理如此极端、稀有的类确实是一种痛苦,这并不奇怪.所以你需要处理 __slots__
(到编写、测试、调试和维护数百行代码只是为了那些极端情况),或者将 99% 的解决方案用六行够了吗?-)
Essentially, __slots__
means that a class is a special, each instance a lightweight "value object" NOT to be subject to further sophisticated manipulation, wrapping, etc, because the need to save a few bytes per instance of that class overrides all the normal concerns about flexibility and so on; it's therefore not surprising that dealing with such extreme, rare classes in the same smooth and flexible way as you can deal with 99%+ of Python objects is truly a pain. So DO you need to deal with __slots__
(to the point of writing, testing, debugging and maintaining hundreds of lines of code just for those corner cases), or will the 99% solution in half a dozen lines suffice?-)
还应该注意的是,这可能会导致内存泄漏,因为创建子类会将子类添加到基类的子类列表中,并且在子类的所有实例都被 GC 时不会被删除.
It should also be noted that this may lead to memory leaks, as creating a subclass adds the subclass to the base class' list of subclasses, and isn't removed when all instances of the subclass are GC'd.
这篇关于用 Python 完全包装一个对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!