Wrapping a class whose methods return instances of that class
我需要编写一个类来包装来自第三方包的类。通常,第三方类具有返回第三方类实例的方法。这些方法的包装版本必须将这些实例转换为包装类的实例,但我无法使其工作。我正在将python 2.7与新样式的类一起使用。
基于创建一个包装类来围绕现有函数调用pre和post函数?,我有以下内容。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | import copy class Wrapper(object): __wraps__ = None def __init__(self, obj): if self.__wraps__ is None: raise TypeError("base class Wrapper may not be instantiated") elif isinstance(obj, self.__wraps__): self._obj = obj else: raise ValueError("wrapped object must be of %s" % self.__wraps__) def __getattr__(self, name): orig_attr = self._obj.__getattribute__(name) if callable(orig_attr): def hooked(*args, **kwargs): result = orig_attr(*args, **kwargs) if result == self._obj: return result return self.__class__(result) return hooked else: return orig_attr class ClassToWrap(object): def __init__(self, data): self.data = data def theirfun(self): new_obj = copy.deepcopy(self) new_obj.data += 1 return new_obj class Wrapped(Wrapper): __wraps__ = ClassToWrap def myfun(self): new_obj = copy.deepcopy(self) new_obj.data += 1 return new_obj obj = ClassToWrap(0) wr0 = Wrapped(obj) print wr0.data >> 0 wr1 = wr0.theirfun() print wr1.data >> 1 wr2 = wr1.myfun() print wr2.data >> 2 wr3 = wr2.theirfun() print wr3.data >> 2 |
现在,为什么在地球上,
抱歉,我不想寻找以下替代方法:
eta:有几个有用的答案引用了
问题出在
你可以把你的EDOCX1[0]稍微改变一下:
1 2 3 4 | def myfun(self): new_obj = copy.deepcopy(self._obj) new_obj.data += 1 return self.__class__(new_obj) # alternative spelling: return type(self)(new_obj) |
解决这个问题的另一种方法是在
与您当前的问题无关,您还可能泄漏
1 2 3 4 5 6 7 8 | def hooked(*args, **kwargs): result = orig_attr(*args, **kwargs) if result == self._obj: return self # fix for leaking objects elif isisntance(result, self.__wraps__): # new type check return self.__class__(result) else: return result # fallback for non-wrappable return values |
问题在于您在
您需要在两个实例之间同步数据值:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | class Wrapper(object): ... def __setattr__(self, attr, val): object.__setattr__(self, attr, val) if getattr(self._obj, attr, self._obj) is not self._obj: # update _obj's member if it exists setattr(self._obj, attr, getattr(self, attr)) class Wrapped(Wrapper): ... def myfun(self): new_obj = copy.deepcopy(self) new_obj.data += 1 return new_obj obj = ClassToWrap(0) wr0 = Wrapped(obj) print wr0.data # 0 wr1 = wr0.theirfun() print wr1.data # 1 wr2 = wr1.myfun() print wr2.data # 2 wr3 = wr2.theirfun() print wr3.data # 3 wr4 = wr3.myfun() print wr4.data # 4 wr5 = wr4.theirfun() print wr5.data # 5 |