我希望完全包装一个对象,以便所有属性和方法请求都被转发到它包装的对象,同时也覆盖我想要的任何方法或变量,以及提供一些我自己的方法。这个包装类应该100%显示为现有类(isinstance
必须像它实际上是类一样工作),但是子类本身不会剪切它,因为我想包装现有的对象。Python中有什么解决方案可以做到这一点吗?我的想法是:
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__
,所以我不知道如何正确地实现这一点。
__getattr__
的优点是只有在属性不存在时才调用它,因此不需要显式列表——任何未定义的内容都将自动获得代理。__setattr__
更复杂,因为它总是被调用。确保在设置自己的属性时使用超类调用或object.__setattr__
;在__setattr__
内使用setattr()
将导致无限递归。最后一个位,影响isinstance,是非常困难的。您可以通过对包装器实例的.
__class__
变量(但这也会重写类字典的解析顺序)的辅助,或者通过使用元类动态构造包装器类型来完成此任务。由于isinstance在Python代码中非常罕见,所以实际上试图欺骗它似乎有些过头了。More information on special attribute access methods.
Even more information on them, plus some help with metaclasses.
请查看http://code.activestate.com/recipes/577555-object-wrapper-class/以获取完整的代码,包括重要的注释。可以归结为:
在大多数情况下,最简单的方法可能是:
以这种方式工作,即以这种方式重新分配self的
__class__
和__dict__
,您只需要提供覆盖——Python的常规属性获取和设置机制将完成其余的工作。。。大部分。只有当
baseObject.__class__
定义了__slots__
时,您才会遇到麻烦,在这种情况下,多重继承方法不起作用,而且您确实需要繁琐的__getattr__
(正如其他人所说,至少您不必担心它将被调用时具有您重写的属性,因为它不会!-),__setattr__
(一个更大的痛苦,因为每个属性都需要调用它)等;使isinstance
和特殊方法工作需要艰苦和繁琐的详细工作。本质上,
__slots__
意味着一个类是一个特殊的,每个实例都是一个轻量级的“值对象”,不需要进行更复杂的操作、包装等,因为每个类实例需要节省几个字节,这覆盖了所有关于灵活性等的正常关注;因此处理以同样平滑灵活的方式处理99%以上的Python对象,这种极端、罕见的类确实是一种痛苦。那么,您需要处理__slots__
(到编写、测试、调试和维护数百行代码的程度,仅仅是为了那些角落的情况),还是说,用6行99%的解决方案就足够了?-)还应该注意的是,这可能会导致内存泄漏,因为创建子类会将子类添加到基类的子类列表中,并且在子类的所有实例都是GC'd时不会被删除
相关问题 更多 >
编程相关推荐