Sma*_*ery 33 python reflection
我想完全包装一个对象,以便所有属性和方法请求转发到它包装的对象,但也覆盖我想要的任何方法或变量,以及提供我自己的一些方法.这个包装类应该作为现有类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)
Run Code Online (Sandbox Code Playgroud)
但我不是那个熟悉的覆盖__getattr__,__setattr__并且__hasattr__,所以我不知道如何获得这一权利.
Ale*_*lli 38
大多数情况下最简单的方法可能是:
class ObjectWrapper(BaseClass):
def __init__(self, baseObject):
self.__class__ = type(baseObject.__class__.__name__,
(self.__class__, baseObject.__class__),
{})
self.__dict__ = baseObject.__dict__
def overriddenMethod(self):
...
Run Code Online (Sandbox Code Playgroud)
以这种方式工作,即通过重新分配自己__class__并__dict__以这种方式,你只需要提供你的覆盖 - Python的正常属性获取和设置机制将完成剩下的工作...... 主要是.
只有在baseObject.__class__定义时才会遇到麻烦__slots__,在这种情况下多重继承方法不起作用,你确实需要繁琐__getattr__(正如其他人所说的那样,至少你不必担心它会被你的属性调用'重新覆盖,因为它不会! - ),__setattr__(更大的痛苦,因为它会被称为每个属性),等等; 制作isinstance和特殊方法的工作需要艰苦而繁琐的细致工作.
本质上,__slots__意味着一个类是一个特殊的,每个实例都是一个轻量级的"值对象",不会受到进一步复杂的操作,包装等的影响,因为需要为该类的每个实例保存几个字节会覆盖所有正常的关注点.灵活性等; 因此,以同样流畅和灵活的方式处理这些极端罕见的类,因为你可以处理99%以上的Python对象,这并不奇怪,这真的很痛苦.那么你需要处理__slots__(为了那些极端情况而编写,测试,调试和维护数百行代码),还是在十几行的99%解决方案就足够了? - )
还应该注意,这可能会导致内存泄漏,因为创建子类会将子类添加到基类的子类列表中,并且在子类的所有实例都是GC时不会被删除.
小智 6
请查看http://code.activestate.com/recipes/577555-object-wrapper-class/以获取完整的代码,包括重要的注释。归结为:
class Wrapper(object):
def __init__(self, obj):
self._wrapped_obj = obj
def __getattr__(self, attr):
if attr in self.__dict__:
return getattr(self, attr)
return getattr(self._wrapped_obj, attr)
Run Code Online (Sandbox Code Playgroud)
小智 5
__getattr__ 它的优点是仅在属性不存在时调用,因此您不需要显式列表 - 您未定义的任何内容都将自动被代理。
__setattr__比较棘手,因为它总是被调用。确保使用超类调用或object.__setattr__在设置自己的属性时;使用setattr()inside__setattr__会导致无限递归。
影响 isinstance 的最后一点非常困难。您可以通过对包装器实例的 . __class__变量(但这也会覆盖类字典解析顺序),或者通过使用元类动态构造您的包装器类型。由于 isinstance 在 Python 代码中非常少见,实际上试图欺骗它似乎有点过分。
| 归档时间: |
|
| 查看次数: |
13258 次 |
| 最近记录: |