Exploring The Lesser Known Features Of Python – Part I

I have been fiddling with Python for some time now and I have to tell you, it just keeps getting better and better! Every time I interact with Python, I stumble across something new. There are so many things you can do with it. It is very well documented and most of the material is available out there. There are some of the lesser known features which are very useful, but you don’t see them often. There are quite a few and I have split it into two parts. You can find the second part here. I have listed the first few here:  

Function Argument Unpacking

When you have to pass something to a function which takes in multiple arguments, you usually need to have separate arguments when you call the function. In Python, you can just unpack a list or a dictionary as function arguments using * and **. For example:

def addThreeNumbers(x, y, z):
     return x+y+z
myNumbers = (4,7,3)
myDictionary = {'y': 2, 'z': 5, 'x': 8}
addThreeNumbers(*myNumbers)
addThreeNumbers(**myDictionary)

This is a very useful feature because lists, tuples and dictionaries are widely used as containers.

Enumeration

An enumeration refers to a collection of items which is a complete, ordered listing of all of the items in that collection. When you are looping over something, you might need the indices along with the items. You can wrap an iterable with ‘enumerate’ and it will yield the item along with its index. For example:

alphabets = ['e', 'l', 'r', 'h', 'f']
for index, item in enumerate(alphabets):
    print index, item
Output:
0 e
1 l
2 r
3 h
4 f

This is a replacement for the following:

for index in range(len(alphabets)): 
    print index, alphabets[index]

Enumeration follows natural ordering starting from 0 by default. But you can also start from an arbitrary index by using:

for index, item in enumerate(alphabets, start=1): 
    print index, item

The above code will index it from 1 and not 0.

Creating Generator Objects

When you are looping over something, you might need intermediate storage. For example:

x = [n for n in foo if bar(n)]

We will then have to use this to get the generator, which is not very optimal. You can use the code below to get out the generator directly and assign it to x:

x = (n for n in foo if bar(n))

Now it means you can do the following:

for n in x: 
    print n

The advantage of this is that you don’t need intermediate storage.This can lead to significant speed up in some cases.

You can append many if statements to the end of the generator, basically replicating nested ‘for’ loops:

n = ((a,b) for a in range(0,2) for b in range(4,6))
for i in n:
    print i
Output:
(0, 4)
(0, 5)
(1, 4)
(1, 5)

The get() method for dictionaries

When the size of your data gets large, dictionaries become very crucial. We use dictionaries a lot of times to organize our data efficiently. The get() method is one of the more secure ways of handling dictionaries and queries related to it.

Dictionaries have a ‘get()’ method. If you do dict[‘key’] and key isn’t there, you get an exception. If you do dict.get(‘key’), you get back ‘None’ if ‘key’ doesn’t exist. You can add a second argument to get that item back instead of ‘None’, eg: dict.get(‘key’, 0).

It’s great for things like adding up numbers:

sum[value] = sum.get(value, 0) + 1

Chaining comparison operators

This is one of those features not available in most languages. You can stick together two or more comparison operators in Python and it works like a charm. For example:

>>> x = 5
 >>> 1 < x < 10
 True
 >>> 10 < x < 20 
 False
 >>> x < 10 < x*10 < 100
 True
 >>> 10 > x <= 9
 True
 >>> 5 == x > 4
 True

Our usual understanding doesn’t exactly apply here. You might be thinking it’s doing 1 < x first, which comes out as True. And then it is comparing True < 10, which is also True. Well, this is not the case here! It’s really translating 1 < x < 10 into 1 < x and x < 10. Similarly, x < 10 < x*10 < 100 is being translated into x < 10 and 10 < x * 10 and x*10 < 100. The advantage is that it’s compact and each term is only evaluated once.

————————————————————————————————-

2 thoughts on “Exploring The Lesser Known Features Of Python – Part I

  1. Pingback: Exploring The Lesser Known Features Of Python – Part II | Perpetual Enigma

  2. Pingback: Exploring The Lesser Known Features Of Python – Part II | Perpetual Enigma

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s