Steven D'Aprano wrote: > > class Rational(object): > > def __init__(self, numerator, denominator): > > print "lots of heavy processing here..." > > # processing ints, floats, strings, special case arguments, > > # blah blah blah... > > self.numerator = numerator > > self.denominator = denominator > > def __copy__(self): > > cls = self.__class__ > > obj = cls.__new__(cls) > > obj.numerator = self.numerator > > obj.denominator = self.denominator > > return obj > > def __neg__(self): > > obj = self.__copy__() > > obj.numerator *= -1 > > return obj > > > Here's a variation on that which is perhaps better suited for objects with > lots of attributes: > > def __copy__(self): > cls = self.__class__ > obj = cls.__new__(cls) > obj.__dict__.update(self.__dict__) # copy everything quickly > return obj
I recently had to do something similar for my ORM, where a user-instantiated object gets expensive default values, but the back end just overwrites those defaults when "resurrecting" objects, so it shouldn't pay the price. However (and this is the tricky part), I also wanted to allow subclasses to extend the __init__ method, so just using cls.__new__(cls) didn't quite go far enough. Here's what I ended up with [1]: def __init__(self, **kwargs): self.sandbox = None cls = self.__class__ if self._zombie: # This is pretty tricky, and deserves some detailed explanation. # When normal code creates an instance of this class, then the # expensive setting of defaults below is performed automatically. # However, when a DB recalls a Unit, we have its entire properties # dict already and should skip defaults in the interest of speed. # Therefore, a DB which recalls a Unit can write: # unit = UnitSubClass.__new__(UnitSubClass) # unit._zombie = True # unit.__init__() # unit._properties = {...} # instead of: # unit = UnitSubClass() # unit._properties = {...} # If done this way, the caller must make CERTAIN that all of # the values in _properties are set, and must call cleanse(). self._properties = dict.fromkeys(cls.properties, None) else: # Copy the class properties into self._properties, # setting each value to the UnitProperty.default. self._properties = dict([(k, getattr(cls, k).default) for k in cls.properties]) # Make sure we cleanse before assigning properties from kwargs, # or the new unit won't get saved if there are no further changes. self.cleanse() for k, v in kwargs.iteritems(): setattr(self, k, v) The _zombie argument is therefore a flag which allows you to keep the initialization code inside __init__ (rather than repeating it inside every method). Robert Brewer System Architect Amor Ministries [EMAIL PROTECTED] [1] http://projects.amor.org/dejavu/browser/trunk/units.py#l552 -- http://mail.python.org/mailman/listinfo/python-list