By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
464,330 Members | 1,106 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 464,330 IT Pros & Developers. It's quick & easy.

Initialize lists; here's why

bartonc
Expert 5K+
P: 6,596
Most other programming languages, as well as Python extension packages require arrays to be initialized to a particular size. Well, it turns out that there is an advantage to doing this with native python lists, too (that is, of course, if you know the size of the list beforehand).

I wrote two tests in a module (call it module1):
Expand|Select|Wrap|Line Numbers
  1. def listAppendTest(n):
  2.     aList = []
  3.     for i in range(n):
  4.         aList.append(i)
  5.  
  6. def listInitTest(n):
  7.     aList = [0] * n
  8.     for i in range(n):
  9.         aList[i] = 1
  10.  
In a second module I use timeit to check this theory:
Expand|Select|Wrap|Line Numbers
  1. import timeit
  2.  
  3. test1ExecStr = \
  4. """from module1 import listAppendTest
  5. listAppendTest(5)"""
  6.  
  7. t = timeit.Timer(test2ExecStr)
  8. print t.timeit()
  9.  
  10. # 22.7464275488
  11.  
  12. test2ExecStr = \
  13. """from module1 import listInitTest
  14. listInitTest(5)"""
  15.  
  16. t = timeit.Timer(test2ExecStr)
  17. print t.timeit()
  18.  
  19. # 17.7503707873
Interesting results, no?
Aug 9 '07 #1
Share this Question
Share on Google+
4 Replies

P: 5
Your testing only five times? I doubt that is statistically sound. What happens when you try 1000?

In any case trying to micromanage performance like this is really the wrong way to programme. First, find if your app is not fast enough, then profile, then fix the bottleneck.

Remember the first rule of optimisation: Don't.
Aug 9 '07 #2

bvdet
Expert Mod 2.5K+
P: 2,851
Your testing only five times? I doubt that is statistically sound. What happens when you try 1000?

In any case trying to micromanage performance like this is really the wrong way to programme. First, find if your app is not fast enough, then profile, then fix the bottleneck.

Remember the first rule of optimisation: Don't.
By my recollection, timeit() defaults to 1000000 iterations.

I routinely optimize as I program where possible. If I know a one method is more efficient than another, I use the most efficient, unless additional functionality is required. Occasionally I use timeit() just so I will know.

Would you use string concatenation repeatedly to build long strings or the string join method? Here's another example:

Method 1:
Expand|Select|Wrap|Line Numbers
  1. def __add__(self, other):
  2.         return Point(*[a+b for a,b in zip(self,other)])
Method 2:
Expand|Select|Wrap|Line Numbers
  1. def __add__(self, other):
  2.         return Point(self.x+other[0], self.y+other[1], self.z+other[2])
Which one should I use?
Aug 9 '07 #3

bartonc
Expert 5K+
P: 6,596
Your testing only five times? I doubt that is statistically sound. What happens when you try 1000?

In any case trying to micromanage performance like this is really the wrong way to programme. First, find if your app is not fast enough, then profile, then fix the bottleneck.

Remember the first rule of optimisation: Don't.
How 'bout 5 million times?
Aug 10 '07 #4

bartonc
Expert 5K+
P: 6,596
Most other programming languages, as well as Python extension packages require arrays to be initialized to a particular size. Well, it turns out that there is an advantage to doing this with native python lists, too (that is, of course, if you know the size of the list beforehand).

I wrote two tests in a module (call it module1):
Expand|Select|Wrap|Line Numbers
  1. def listAppendTest(n):
  2.     aList = []
  3.     for i in range(n):
  4.         aList.append(i)
  5.  
  6. def listInitTest(n):
  7.     aList = [0] * n
  8.     for i in range(n):
  9.         aList[i] = 1
  10.  
In a second module I use timeit to check this theory:
Expand|Select|Wrap|Line Numbers
  1. import timeit
  2.  
  3. test1ExecStr = \
  4. """from module1 import listAppendTest
  5. listAppendTest(5)"""
  6.  
  7. t = timeit.Timer(test2ExecStr)
  8. print t.timeit()
  9.  
  10. # 22.7464275488
  11.  
  12. test2ExecStr = \
  13. """from module1 import listInitTest
  14. listInitTest(5)"""
  15.  
  16. t = timeit.Timer(test2ExecStr)
  17. print t.timeit()
  18.  
  19. # 17.7503707873
Interesting results, no?
Interestingly, (and this is something that I've been meaning to do for a long time) the import is taking a significant amount of time.
Expand|Select|Wrap|Line Numbers
  1. import timeit
  2.  
  3. test1ExecStr = \
  4. """from test3 import listAppendTest"""
  5.  
  6. t = timeit.Timer(test1ExecStr)
  7. print t.timeit()
  8.  
  9. # 8.945650355
  10.  
  11. test2ExecStr = \
  12. """from test3 import listInitTest"""
  13.  
  14. t = timeit.Timer(test2ExecStr)
  15. print t.timeit()
  16.  
  17. # 8.87637339383
Aug 10 '07 #5

Post your reply

Sign in to post your reply or Sign up for a free account.