I'll start a series of posts about Python idioms.
What is a programming idiom? According to Wikipedia's Programming Idiom article, a programming idiom is defined as "the use of an unusual or notable feature that is built in to a programming language".
What is a programming idiom? According to Wikipedia's Programming Idiom article, a programming idiom is defined as "the use of an unusual or notable feature that is built in to a programming language".
Python is very rich in useful idioms. Python programmers who take advantage of them are known as pythonistas. On that sense, I highly recommend you to read the famous article Code like a Pythonista: Idiomatic Python by David Goodger.
Once defined the concept of programming idiom and introduced the concept pythonista, let's talk about one of favorite idioms: building strings from substrings.
Imagine that you have a list of strings,
bands = ['Machine Head','Metallica','Opeth','Veil of Maya']
and you want to concatenate each item in the list to form a unique comma separared string. If you come from the C, Java syntax world, you would write something like this:
output = '' for band in bands[:-1]: output += band + ', ' output += bands[-1]If you print the content of the output variable, you will get a list of the bands:
print output >>> Machine Head, Metallica, Opeth, Veil of Maya
This is a very inefficient way to concatenate strings in Python because in each iteration of the for loop, a temporal string is generated before the string addition and thrown away after.
The pythonic way is faster and more elegant:
The pythonic way is faster and more elegant:
>>> print ', '.join(bands) Machine Head, Metallica, Opeth, Veil of Maya
I coded a small example to compare the performance of both techniques:
from functools import wraps import time def timed(f): @wraps(f) def wrapper(*args, **kwds): start = time.clock() result = f(*args, **kwds) elapsed = time.clock() - start #print "%s took %d time to finish" % (f.__name__, elapsed) print "%.5gs" % (elapsed) return result return wrapper bands = ['Machine Head','Metallica','Opeth','Veil of Maya']*100000 @timed def func1(): output = '' for band in bands[:-1]: output += band + ', ' output += bands[-1] return output @timed def func2(): output = ', '.join(bands) return output func1() func2()
The result is:
$ python test.py
0.07s
0.01s
If we increase one order of magnitude the bands list:
$ python test.py
0.62s
0.1s
the difference in performance becomes more relevant.
PS: In my toy example, I used the timed decorator that can be found in this stackoverflow thread.
PS: In my toy example, I used the timed decorator that can be found in this stackoverflow thread.
No comments:
Post a Comment