Copy with __slots__

Griebel, Peer Peer.Griebel at entire.de
Thu Sep 19 09:14:39 CEST 2002


> It's of course not a matter of new vs old classes -- new classes
> would let you use the dictionary-update method just as well... as
> long as you didn't use __slots__.

Ok. I was a little unprecise.
 
> Regarding performance -- *measure* things, man!  Intuition about
> what runs slowly, what rapidly, is notoriously misleading.  E.g.:
> 
> import time, copy
> 
> class noslots(object):
>     pass
> 
> class withslots(object):
>     __slots__ = 's1', 's2'
>     def __copy__(self):
>         result = self.__class__.__new__(self.__class__)
>         result.s1 = self.s1
>         result.s2 = self.s2
>         return result

...

> [alex at lancelot ~]$ python -O slorno.py
> 1.04 noslots
> 0.29 withslots
> 
> "much more slowly", hmm...?  Looks over 3 times faster to *ME*...

Sorry. But even timing shows that slots are slower. My class has exaclty 10
attributes (some more that your example) which have to be copied. Copying
each slot explicitly takes 2.28 sec (100000 iterations).

Using a class without slots and following method:
    def __copy__(self):
        c = _EmptyClass()
        c.__class__ = self.__class__
        c.__dict__.update(self.__dict__)
        return c
copying takes only 1.4 sec. So there is some price to pay to use slots. (To
be precise: In my code I directly call __copy__ but do not use copy.py -
because it's much faster. And my method isn't called __copy__ but clone.)

BUT: I just timed my whole program. Although copying takes more time the
program as a whole runs faster! The runtime drops from 16.3 sec to 14.5 sec.
So using slots seems to speed up other accesses to attributes significantly.

> > 2. The approach is error prone. When simply updating a dict 
> I'm not going
> > to miss a newly added attribute. But using your method I 
> have to remember
> > the method whenever I add an attribute.
> 
> Yes, that IS part of the price you pay for getting the optimization
> that __slots__ affords: you do have to know exactly what you're doing.
> Thus, __slots__ should be used when the program is working, in the
> optimization phase, for classes such that saving a __dict__ per
> instance IS an important optimization, only (classes of which MANY
> instances exist, basically).

You are right. Saving a dict made me switch to use slots. And now I learnt
that I also can save time using slots.

So my advice now is: Use slots! The program runs faster, uses less memory.
And explicitly coding a __copy__ function which copies each attribute isn't
a bad thing per se. It makes the things more explicit.


One more thing: Does anybody know if copy.py in CVS correctly handles
objects with slots? I think it should be modified...

Peer




More information about the Python-list mailing list