Copy with __slots__
Alex Martelli
aleax at aleax.it
Wed Sep 18 16:56:17 EDT 2002
Christian Tismer wrote:
...
> You can get this to the single slot-level speed by doing
> the slot grabbing phase of above once, after the class
It's an important speed-up, yes -- but still quite a bit
slower than dealing with a single slot.
> speed can be found by not caching the __slots__ but their
> get/set wrappers and then just calling these with the new
> instance...
I've done that too (as a function, but would be trivial to
wrap as a custom metaclass):
class acceled(withslots):
def __copy__(self):
result = self.__class__.__new__(self.__class__)
for get, set in self._accel:
set(result, get(self))
def makeaccel(aclass):
slot_names_seen = {}
slot_gets_sets = []
for base in aclass.__mro__:
for s in getattr(base, '__slots__', []):
if s in slot_names_seen: continue
slot_names_seen[s] = True
slot = getattr(base, s)
slot_gets_sets.append((slot.__get__,slot.__set__))
aclass._accel = slot_gets_sets
makeaccel(acceled)
[alex at lancelot ~]$ python -O slorno.py
1.10 noslots
0.67 withslots
0.37 acceled
[alex at lancelot ~]$ python -O slorno.py
1.14 noslots
0.69 withslots
0.37 acceled
[alex at lancelot ~]$ python -O slorno.py
1.10 noslots
0.68 withslots
0.36 acceled
Not the 0.28 or so that I got by "unwrapping the loop" (i.e., just
coding out the assignment for each slot!), but still, an important
speedup, as I said. Thanks on behalf of the OP!
It's not clear from the above what proportion of the gain is due
to just doing some of the work in advance, what to extracting
the getter and setter, what simply to avoidance of double work
that class withslots did because it copied attribute s1 twice. As
the OP clearly needs practice in measuring Python runtimes (he
guessed that the 0.28 blazing-fast verson would be SLOWER
than the original 1.10 one, and didn't even THINK of doing a
measurement to double check his intuition...!!!), I guess I'll leave
this homework to him as a useful exercise:-).
Alex
More information about the Python-list
mailing list