Python Tricks for Better Code
A compilation of very useful Python tricks for better code. All examples are Python 2.7 and Python 3 compatible unless stated otherwise.
Enumerate
When working with items in a list and we want to print or handle each item's index, instead of using a counter variable:
# Bad way
i = 0
for place in places:
print(i, place)
i += 1
We can use enumerate
to improve our code:
for i, place in enumerate(places):
print(i, place)
enumerate
returns a list of indexes along with each item in the list.
Using zip
Sometimes it happens that we have two different lists and we want to iterate through both of these two lists at the same time. An ugly approach to this situation is to obtain the length of one of the lists first and then iterate through one of them, while handling the other list inside the loop:
# Bad way
list_1 = ['123', 'KSQR', '12GKAL']
list_2 = ['65DD', '12DD', '123HGH']
for i in range(len(list_1)):
a = list_1[i]
b = list_2[i]
print(a, b)
Instead, we can use zip
for more concise and better looking code:
for a, b in zip(list_1, list_2):
print(a, b)
zip
will take two or more lists and zip them together. This means that the resulting list will have pairs of each item from each list as a single item.
Swapping Variable Values
When we want to swap the values between two variables, a common and unpractical approach is to create a third temporary variable to help with the swapping:
a = 5
b = -5
# Bad way
tmp = a
a = b
b = tmp
We can improve this by using a technique called tuple unpacking:
a, b = b, a
Default Dictionary Values
When trying to obtain a value from a dictionary, is necessary to check first if the dictionary already has the key we are using to obtain the value, otherwise we will get a KeyError
error.
Usually checks like these are done like this:
# Bad way
if 'John' in salaries:
salary_john = salaries['John']
However there is a better way using a dictionary's get
function:
salary_john = salaries.get('John', 0)
With the get
function we can immediately get the value for the 'John'
key if it exists, while also providing a fallback value of 0
if the key is not in the dictionary.
For … else
Python for
loops have a very useful else
statement. In the context of loops in Python, the else
statement means that if no break occurs, the code inside the else
will be executed.
The main use case for this behaviour is to implement search loops, where you’re performing a search for an item that meets a particular condition, and need to perform additional processing or raise an informative error if no acceptable value is found:
for x in data:
if acceptable(x):
break
else:
raise ValueError("No acceptable value in {!r:100}".format(data))
# Continue calculations with x
File Reading
When opening files, it is very common to see a variable assigned with open()
and reading the contents with another assignment and read()
:
# Bad way
f = open('todo.txt')
content = f.read()
for line in content.split('\n'):
print(line)
f.close()
A better way is to use the with
statement. The file object also adds support for iteration for more concise code:
with open('todo.txt') as f:
for line in f:
print line
Everything that is inside the with
“block” will be executed while the file is open. When this is finished, the file will be closed automatically.
List Comprehensions
List comprehensions allow us to define a list's contents in-line without its declaration. Here is an example without using list comprehension:
list = []
for i in (1, 2, 3):
list.append(i)
And here is the same example using a list comprehension:
list = [i for i in (1, 2, 3)]
Neat! We can use multiple for
statements together and if
statements to filter out items. Using list comprehensions instead of for
loops is a nice way to quickly define lists.
Advanced Unpacking
Similar to the tuple unpacking trick shown before, in Python 2 we can use advanced unpacking in the following way:
a, b = range(2)
# a => 0
# b => 1
With Python 3 we can also obtain the remainder of the sequence. We can actually obtain the remainder from anywhere in the list:
a, *rest, b = range(10)
# a => 0
# *rest => [2, 3, 4, 5, 6, 7, 8, 9]
# b => 10
a, *rest, b = range(10)
# a => 0
# b => 9
# rest => [1, 2, 3, 4, 5, 6, 7, 8]
Enum Classes
Enumerated types were added to the standard library in Python 3.4+, allowing us to do the following:
from enum import Enum
class Color(Enum):
red = 1
blue = 2
green = 3
red = Color.red