Posts Tagged: "idiomatic python"

Idiomatic Python – Writing better Python

- - Python, Tutorials

This is a follow-up post of Idiomatic Python – Looping Approaches. The purpose of the article is to highlight on better code and encourage it.

Looping over dictionary keys

>>> books_price = {
...     'Clean Code: A Handbook of Agile Software Craftsmanship': 42.17,
...     'The Self-Taught Programmer: The Definitive Guide to Programming Professionally': 15.09,
...     'The Art of Computer Programming, Volumes 1-4A Boxed Set': 174.96
... }
>>> for book in books_price:
...     print(book)
...

The above code snippet should not be used for mutating the dictionary. You do not want to change the size of the dictionary while you actively iterate over it.

>>> for book in books_price:
...     if book.startswith('The'):
...             del books_price[book]
... 
Traceback (most recent call last):
  File "", line 1, in 
RuntimeError: dictionary changed size during iteration
>>>
>>> books_price
{'Clean Code: A Handbook of Agile Software Craftsmanship': 42.17, 'The Self-Taught Programmer: The Definitive Guide to Programming Professionally': 15.09}
>>>

If by any chance you wrapped the above code around a broad exception, you will then have an inconsistent data. See how in the above example one key value pair has been removed from the books_price dictionary.

Proper way of mutating dictionary while iterating over it’s keys:
>>> books_price = {'Clean Code: A Handbook of Agile Software Craftsmanship': 42.17, 'The Art of Computer Programming, Volumes 1-4A Boxed Set': 174.96, 'The Self-Taught Programmer: The Definitive Guide to Programming Professionally': 15.09}
>>>
>>> for book in books_price.keys():
...     if book.startswith('The'):
...         del books_price[book]
...
>>>
>>> books_price
{'Clean Code: A Handbook of Agile Software Craftsmanship': 42.17}
>>>

The books_price.keys() copies all the keys of the books_price dictionary and makes a list. What we are really doing is iterating over the list and modifying the dictionary. This way we avoid trying to mutate the dictionary while actively iterating on it.

Note that in python3 dict.keys() only creates an iterable that provides a dynamic view on the keys of the dictionary while not actually making a new list of keys. This is also known as dictionary view. Therefore you have to explicitly pass the dict.keys() to a list class i.e list(dict.keys())

Construct a dictionary from sequence pairs

>>> books = [
... 'Clean Code: A Handbook of Agile Software Craftsmanship',
... 'The Art of Computer Programming, Volumes 1-4A Boxed Set',
... 'The Self-Taught Programmer: The Definitive Guide to Programming Professionally']
>>> prices = [42.17, 174.96, 15.09]
>>>
>>> from itertools import izip
>>> books_price = dict(izip(books, prices))
>>> books_price
{'Clean Code: A Handbook of Agile Software Craftsmanship': 42.17, 'The Art of Computer Programming, Volumes 1-4A Boxed Set': 174.96, 'The Self-Taught Programmer: The Definitive Guide to Programming Professionally': 15.09}
>>>

 

You could also use zip instead of izip. zip provides a list while izip provides an iterator instead of a list, hence the name izip (I for iterator). In python3 though, zip is equivalent to izip.

 

>>> books_price = dict(zip(books, prices))
>>> books_price
{'Clean Code: A Handbook of Agile Software Craftsmanship': 42.17, 'The Art of Computer Programming, Volumes 1-4A Boxed Set': 174.96, 'The Self-Taught Programmer: The Definitive Guide to Programming Professionally': 15.09}
>>>

Looping over dictionary keys and values

>>> for key in books_price:
...     print key, ' => ', books_price[key]
...
Clean Code: A Handbook of Agile Software Craftsmanship  =>  42.17
The Art of Computer Programming, Volumes 1-4A Boxed Set  =>  174.96
The Self-Taught Programmer: The Definitive Guide to Programming Professionally  =>  15.09
>>>

While the above code works as expected, it needs to re-hash every key and do a value lookup. OR you could do something like this:

>>> for key, value in books_price.items():
...     print key, " => ", value
...
Clean Code: A Handbook of Agile Software Craftsmanship  =>  42.17
The Art of Computer Programming, Volumes 1-4A Boxed Set  =>  174.96
The Self-Taught Programmer: The Definitive Guide to Programming Professionally  =>  15.09
>>>

The problem with the above code is that it creates a huge list of the keys and values. A better approach would be:

>>> for key, value in books_price.iteritems():
...     print key, " => ", value
...
Clean Code: A Handbook of Agile Software Craftsmanship  =>  42.17
The Art of Computer Programming, Volumes 1-4A Boxed Set  =>  174.96
The Self-Taught Programmer: The Definitive Guide to Programming Professionally  =>  15.09
>>>

iteritems() returns an iterator instead of list. Note that in python3, iteritems() is not present and python3’s items() is equivalent to iteritems() in python2.

Subscribe to my blog for more interesting contents

You should read the predecessor article to this one which encourages on writing better python circling around list looping approaches at http://www.thetaranights.com/idiomatic-python-looping-approaches/

Idiomatic Python – Use of Falsy and Truthy Concepts

- - Python, Tutorials

Out of many, one reason for python’s popularity is the readability. Python has code style guidelines and idioms and these allow future readers of the code to comprehend to the intentions of it. It is highly important that the code is readable and concise. One such important tip is to use falsy and truthy concepts.

It should be at our best interest to avoid direct comparison to True, False, None. As such we should be well known about truthy and falsy concepts.

Truthy refers to the values that shall always be considered true. Similarly falsy refers to the values that shall always be considered false.

An empty sequence such as an empty list [], empty dictionaries, 0 for numeric, None are considered false values or falsy. Almost anything excluding the earlier mentioned are considered truthy.

An example of a code snippet that is considered bad:

i = 0
if i == 0:
    foo()
    # do something
else:
    bar()
    # do something else
x = True
if x == True:
    foo()
    # do something
else:
    bar()
    # do something else
numbers_list = [1, 2, 3, 4]
if len(numbers_list) > 0:
    foo()
    # do something

An example of code snippet that is considered relatively wise:

i = 0
if not i:
    foo()
    # do something
else:
    bar()
    # do something else
x = True
if x:
    foo()
    # do something
else:
    bar()
    # do something else
numbers_list = [1, 2, 3, 4]
if numbers_list:
    foo()
    # do something