Question

I have a class which contains a number of class variables:

c_dict1, c_dict2, c_dict3

They are all dictionaries, and store some values using some of the instance variables below as keys.

I have a few hundreds of instances of this class, and each has the following instance variables:

i_key1, i_key2, i_key3, i_attr1, i_attr2, i_attr3

They first three (i_key*) can be used to look up the latter three (i_attr*) in the class variables. In other words:

self.i_attr1 = MyClass.c_dict1(i_key1)
self.i_attr2 = MyClass.c_dict2(i_key2)
self.i_attr3 = MyClass.c_dict3(i_key3)

My question is:

In terms of performance, should I maintain the instance variables i_attr* locally, or should I access them via dictionary lookup using class variables c_dict*? Obviously, doing via the class variables get rid of three pointers per instance, which may save some memory, but is there any significant speed penalty for doing it this way?

Was it helpful?

Solution

In terms of performance, should I maintain the instance variables i_attr* locally, or should I access them via dictionary lookup using class variables c_dict*?

If this sort of constant-time micro-optimisation is important and not premature, probably don't use python.

I strongly suspect that this is premature optimisation, and you have not identified this as a hotpot, because if you had, you could just profile your code both ways, and wouldn't be asking here.

You can get much more of a speedup by worrying about your architecture, whether you should be running a long-lived process which can take advantage of PyPi, etc.

OTHER TIPS

There is no general answer to your question in terms of performance as it depends on the frequency of access and how you use the results, you just have to try and see. Run your code with timeit or profile to see the results.

If you want to keep the c_dictN in sync with i_attrN, it is probably better to use something like:

self.i_attrN = property(lambda self:       MyClass.c_dictN[i_keyN], 
                        lambda self, val:  MyClass.c_dictN[i_keyN] = val)

(note that you can also use setattr and getattr to set all fields in a loop if they are really named like your example).

If you can do like the above, and you can change the contract of your class, another solution would be to use an indexed accessor like:

def __getitem__(self, idx):
    return MyClass.c_dict[idx][self.i_key[idx]]

def __setitem__(self, idx, val):
    MyClass.c_dict[idx][self.i_key[idx]] = val

Then you could change the access from

a = myobj.i_attrN
myobj.i_attrN = b

to

a = myobj[N]
myobj[N] = b
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top