tips on writing beautiful code in python – part 1

I’ve been programming in Python for over 7 years now and I must say its the most beautiful language I have ever worked with. They say “beauty lies in the eyes of the beholder”, but when it comes to Python, the language itself is designed to look beautiful. Ok, maybe I am a bit biased !!

The following tips are heavily influenced by the various talks I watched, by Raymond Hettinger, the co-author of Python (who I admire) and a few of my own experiences with Python. Since this is a list of things I collected over the years, I am not able to attribute these to the appropriate authors, but please accept my sincere thanks.

# tuple unpacking

When you want to do something like swapping the values of two variables a, b

temp = a
a = b
b = temp

a better (and safer) way of doing this is by using tuples to unpack.

(a, b) = (b, a)

# join() to concatenate strings in a list

Say, you have a list of words in a sentence and you want to join the words back into a sentence, use the str class’ .join() method.

list_of_words = ['The', 'quick', 'brown', 'fox', 'jumped', 'over', 'the', 'lazy', 'dog']
print ' '.join(list_of_words)

# prints 'The quick brown fox jumped over the lazy dog'.
# Note, ' ' is not an empty string, but a single space. 
# This adds the single space between each word.

# range() vs xrange()

If you have to iterate over a list of integers, you’d normally do

for i in range(10):
    print i

range(10) returns a list of integers from 0 to 9. But what if you need to iterate over a million integers? range(1000000) would return a massive list in memory. So, instead of range(), use xrange() function, which does the same as range(), but returns an iterator instead of the whole list.

Note: xrange was renamed to range in python 3 and it returns an iterator.

# looping over a list in reverse order

reversed(list) function takes a list and returns an iterator that yields items from the list in reverse order.

l = [1,2,3,4]
for i in reversed(l):
    print i

# prints 4,3,2,1

# looping over a list when you need the index of the list

When you need the list item and its index position in the list when you are looping over it, the usual way to do it in non-pythonic way is..

fruits = ['apple', 'orange', 'mango']
for index in range(len(fruits)):
    print index, fruits[index]

In python, use enumerate() function, which returns a tuple of (index, item) from the list.

fruits = ['apple', 'orange', 'mango']
for index, fruit in enumerate(fruits):
    print index, fruit

# creating a dictionary from two lists

If you have two lists names ‘keys’ and ‘values’ as below,

keys = ['AAPL', 'MSFT', 'GOOGL']
values = [117.91, 62.84, 825.21]

and you want to create a dictionary like

{'AAPL': 117.91, 'GOOGL': 825.21, 'MSFT': 62.84}

use the zip() function

dict(zip(keys, values))

If the lists are big, a better way of doing it is by using itertools.izip function, which returns an iterator instead of a huge list of tuples in memory.

from itertools import izip
dict(zip(keys, values))

# sorting a list

Easily done using sorted() function

tickers = ['AAPL', 'MSFT', 'GOOGL']
print(sorted(tickers))

# else in a for loop

Every for loop has an else condition which we normally don’t use, but has a useful function in some specific situations like breaking out of a for loop.

def find(sequence, target):
    for value in enumerate(sequence):
        if value == target:
            break
    else:
        return -1
    return i

# looping over dictionaries

iteritems() function on a dictionary object returns an iterator of tuple (key, value).

for key, value in d.iteritems():
    print key, '-->', value

# defaultdict()

defaultdict() of the collections library is the way to create dictionaries that returns default values instead of throwing a KeyError.

from collections import defaultdict
d = defaultdict(int)
print d['some_key_that_doesnot_exist']

# print 0 instead of throwing a KeyError.

————————————————

More to come in future posts.

Leave a Reply

Your email address will not be published. Required fields are marked *