Duncan Booth duncan at NOSPAMrcp.co.uk
Wed Sep 11 10:13:24 CEST 2002

"Steven Shaw" <steven_shaw at iprimus.com.au> wrote in 
news:3d7e209a_1 at news.iprimus.com.au:

> Does this mean that the attributes are stored in a more efficient way?
> Is there a way to implement "record-based" object layout rather than
> "associative-array based" object layout?
It very much depends what you mean by 'more efficient'. Using object-
derived classes and __slots__ means that each class no longer has the 
overhead of creating a dictionary for the instance attributes, so you are 
saving the memory overhead of the dictionary. On the other hand, object-
derived classes seem to be slower to create, and setting attributes defined 
in object-derived classes is also slower than setting attributes in old-
style classes (although setting __slots__ attributes seems to be faster 
than setting other attributes).

The code below gives these timings on my machine:
3.84s: 1000000 x New()
3.89s: 1000000 x New2()
2.39s: 1000000 x Old()
5.19s: 10000 x attributes(<class '__main__.New'>)
5.81s: 10000 x attributes(<class '__main__.New2'>)
4.17s: 10000 x attributes(__main__.Old)
class Old: pass

class New(object):
    __slots__ = ['a', 'b', 'c', 'd']

# New-style, but not using slots.
class New2(object): pass

def timeit(repeat, fn, *args, **kw):
    import time
    start = time.time()
    for i in xrange(repeat):
        fn(*args, **kw)
    end = time.time()
    # Format arguments for printout
    argstring = ', '.join(
        [str(a) for a in args] +
        [ '%s=%s' % (k, v) for k, v in kw.items()])
    if len(argstring) > 60:
        argstring = argstring[:57] + '...'
    print "%.2fs: %d x %s(%s)" % ((end-start), repeat, fn.__name__, 

def attributes(klass):
    inst = klass()
    inst.a = 1
    for i in range(100):
        inst.b = inst.a+1
        inst.c = inst.a+2
        inst.d = inst.a+4
        inst.a += 5

timeit(1000000, New)
timeit(1000000, New2)
timeit(1000000, Old)
timeit(10000, attributes, New)
timeit(10000, attributes, New2)
timeit(10000, attributes, Old)

Duncan Booth                                             duncan at rcp.co.uk
int month(char *p){return(124864/((p[0]+p[1]-p[2]&0x1f)+1)%12)["\5\x8\3"
"\6\7\xb\1\x9\xa\2\0\4"];} // Who said my code was obscure?

More information about the Python-list mailing list