I have a function which runs a numerical simulation. The inputs to the main function are so many that I have created a class (with no methods) to store them all, something like:
myinput=MyInput()
myinput.file1 = file1
myinput.file2 = file2
myinput.something = something
run_model(myinput)
I was thinking that one way to optimise the code is to create local variables so that the many functions which are part of the program read the local variables without needing to access the objects of the MyInput class. This is because most of these variables need to be accessed multiple times, and I imagine there is a cost to accessing classinstance.attribute instead of localvariable. E.g.:
def myfun(myinput):
something=myinput.something
step1=fun1(something)
step2=fun2(something)
out=something + step1 + step2
Is this line of reasoning correct? I have tested it with the code below, and I see an improvement of about 30%. Is there another way to improve it? Is this to be expected? Before I embark on refactoring all my code, I'd like to understand the theory behind it.
Why is accessing myclass.attributes so costly in terms of performance? Is it a limitation of Python or is this common to other languages, too?
import timeit
class MyClass:
def __init__(self,a,b,c,d,e):
self.a=a
self.b=b
self.c=c
self.d=d
self.e=e
def fun_local(myclass, size):
a=myclass.a
b=myclass.b
c=myclass.c
d=myclass.d
e=myclass.e
for i in range(size):
x = (a+b)**c+d*e
def fun(myclass, size):
for i in range(size):
x= (myclass.a + myclass.b)** myclass.c + myclass.d * myclass.e
myclass=MyClass(8,4,4,10,100)
rep=3
num=10
size=int(1e6)
res_local = min( timeit.Timer( "fun_local(myclass, size)", globals=globals() ).repeat(repeat= rep, number = num ) )
res_noloc = min( timeit.Timer( "fun(myclass, size)", globals=globals() ).repeat(repeat= rep, number = num ) )