On Mon, Aug 13, 2012 at 10:28 PM, Steven D'Aprano <st...@pearwood.info> wrote: > >> def new_with_overrides(obj1, **kwds): >> obj2 = obj1.__new__(obj1.__class__) >> obj2.__dict__.update(obj1.__dict__) >> for k, v in kwds.items(): >> if k in obj2.__dict__: >> obj2.__dict__[k] = v >> return obj2 > > In general, this can fail too. The instance may have __slots__, it > may not have a __dict__ at all, it may be using properties or > __getattr__ etc. to implement computed attributes. All sorts of things > can go wrong when copying arbitrary instances. That's why there is an > entire protocol so that types can make themselves copyable. > > Matt, if you're trying to make a "copy any instance" utility function, you > are re-inventing the wheel. See the copy module instead.
Right, I overlooked classes with __slots__ and that override __new__ and other special methods. copy() is the better and more customizable solution. This is the same route for customizing the pickle of an object, so the pickle docs should help: http://docs.python.org/library/pickle.html#pickling-and-unpickling-normal-class-instances The default __reduce__(2) will call __getnewargs__ and __getstate__ to create an info tuple used to construct a copy. The args from __getnewargs__ are used to call a __newobj__ function that in turn calls cls.__new__(cls, *args) to create a new instance. The copy reconstructor will update the new instance with the state from __getstate__ if it's non-false. If the state is a tuple, the 2nd item should be the slots state. The reconstructor uses __setstate__ if it exists. Otherwise it updates the instance dict with state[0] if it's non-false, and uses setattr to set slots if state[1] is non-false. class Test(object): def __new__(cls, v): print '__new__', v obj = object.__new__(cls) obj.new_attr = v return obj def __getnewargs__(self): print '__getnewargs__' return (self.new_attr, ) def __getstate__(self): print '__getstate__' return ({'attr': 'value'}, {'slot_attr': 'value'}) def __setstate__(self, state): print '__setstate__', state >>> t1 = Test('test') __new__ test >>> t2 = copy.copy(t1) __getnewargs__ __getstate__ __new__ test __setstate__ ({'attr': 'value'}, {'slot_attr': 'value'}) _______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor