It's faster and more readable to construct the object and then attach it to self
.
class Test1(object):
def __init__(self):
d = {}
d['a'] = 1
d['b'] = 2
d['c'] = 3
self.d = d
class Test2(object):
def __init__(self):
self.d = {}
self.d['a'] = 1
self.d['b'] = 2
self.d['c'] = 3
import dis
print "Test1.__init__"
dis.dis(Test1.__init__)
print "Test2.__init__"
dis.dis(Test2.__init__)
disassemles to:
Test1.__init__
4 0 BUILD_MAP 0
3 STORE_FAST 1 (d)
5 6 LOAD_CONST 1 (1)
9 LOAD_FAST 1 (d)
12 LOAD_CONST 2 ('a')
15 STORE_SUBSCR
6 16 LOAD_CONST 3 (2)
19 LOAD_FAST 1 (d)
22 LOAD_CONST 4 ('b')
25 STORE_SUBSCR
7 26 LOAD_CONST 5 (3)
29 LOAD_FAST 1 (d)
32 LOAD_CONST 6 ('c')
35 STORE_SUBSCR
8 36 LOAD_FAST 1 (d)
39 LOAD_FAST 0 (self)
42 STORE_ATTR 0 (d)
45 LOAD_CONST 0 (None)
48 RETURN_VALUE
Test2.__init__
12 0 BUILD_MAP 0
3 LOAD_FAST 0 (self)
6 STORE_ATTR 0 (d)
13 9 LOAD_CONST 1 (1)
12 LOAD_FAST 0 (self)
15 LOAD_ATTR 0 (d)
18 LOAD_CONST 2 ('a')
21 STORE_SUBSCR
14 22 LOAD_CONST 3 (2)
25 LOAD_FAST 0 (self)
28 LOAD_ATTR 0 (d)
31 LOAD_CONST 4 ('b')
34 STORE_SUBSCR
15 35 LOAD_CONST 5 (3)
38 LOAD_FAST 0 (self)
41 LOAD_ATTR 0 (d)
44 LOAD_CONST 6 ('c')
47 STORE_SUBSCR
48 LOAD_CONST 0 (None)
51 RETURN_VALUE
You can see that STORE_ATTR
only gets called once doing it the first way at the end. Doing it the other way, STORE_ATTR
still gets called right at the beginning but now LOAD_ATTR
gets called for every access to the dictionary. The more assignments there are, the higher the cost. Every other instruction is the same. It's still a ridiculously small cost.
This trick can be exploited to make loops with many iterations run faster. It's not uncommon to see things like
foo = self.foo
factorial = math.factorial
for x in really_big_iterator:
foo(factorial(x))
another trick is to pass global functions as default arguments to a function that has a loop like that or gets called a whole bunch to save some attribute lookups: it's in the local scope which is the first one looked in.
def fast(iterators, sum=sum):
for i in iterator:
yield sum(i)
now sum is right in the local scope.