Best Practices For Writing Clean Pythonic Code

dollardhingra

Dollar Dhingra

Posted on December 11, 2021

Best Practices For Writing Clean Pythonic Code

Introduction

This article is a collection of best practices for more idiomatic python code especially if you are new to python.

Contribute

Feel free to contribute to this list, and I will thank you by including a link to your profile with the snippet!

1. Catching Exceptions

This is a sure-shot way to get your code into trouble

# very bad practice
try:
    do_something()
except:
    pass

# A slightly better way(included logging), but still a bad practice:
try:
    do_something()
except Exception:
    logging.exception() # although, logging is a good practice

# When we don't use `Exception` we will also be catching events like system exit. 
# So, using Exception means that we are only catching Exceptions.

# A better way:
try:
    do_something()
except ValueError:
    logging.exception()
    # some code to handle your exception gracefully if required

Enter fullscreen mode Exit fullscreen mode

Here we have used a specific type of Exception i.e. ValueError.

2. Name Casing


# using camelCase is not a convention in python
def isEmpty(sampleArr):
    ...

# instead use snake_case in python
def is_empty(sample_arr):
    ...
Enter fullscreen mode Exit fullscreen mode

In python, snake_case is preferred for variables, functions and method names. However, for classes, PascalCase is used.

3. Chained comparison operators

There are multiple ways of comparing in Python:

# Don't do this:
if 0 < x and x < 10:
    print('x is greater than 0 but less than 10')


# Instead, do this:
if 0 < x < 10:
    print('x is greater than 0 but less than 10')
Enter fullscreen mode Exit fullscreen mode

4. Mutable default arguments


# wrong way!
# a sure shot way to get some unintended bugs in your code
def add_fruit(fruit, box=[]):
    box.append(fruit)
    return box


# correct way!
# recommended way for handling mutable default arguments:
def add_fruit(fruit, box=None):
    if box is None:
        box = []

    box.append(fruit)
    return box
Enter fullscreen mode Exit fullscreen mode

Read more about mutable default arguments here

5. String Formatting


# Avoid using it
# %-formatting
name = "James Bond"
profession = "Secret Agent"
print("Hello, %s. You are a %s." % (name, profession))

# slightly better
# str.format()
print("Hello, {}. You are a {}.".format(name, profession))

# Short, crisp and faster!
# f-strings
print(f"Hello, {name}. You are a {profession}.")
Enter fullscreen mode Exit fullscreen mode

The f in f-strings may as well stand for "fast." f-strings are faster than both %-formatting and str.format(). (Source)

6. Top-level script environment

Executes only if it is run as a script and not as a module

# Filename: run.py

if __name__ == '__main__':
    print('Hello from script!')
Enter fullscreen mode Exit fullscreen mode
$ python run.py
$ Hello from script!
Enter fullscreen mode Exit fullscreen mode

Hello from script! will not be printed if the module is imported into any other module.

7. Conditional expressions

if x < 10:
    return 1
else:
    return 2
Enter fullscreen mode Exit fullscreen mode

Can be reduced to this one:

return 1 if x < 10 else 2
Enter fullscreen mode Exit fullscreen mode

8. Iterating over an iterator

You don’t necessarily need to iterate over the indices of the elements in an iterator if you don’t need them. You can iterate directly over the elements.
This makes your code more pythonic.

list_of_fruits = ["apple", "pear", "orange"]

# bad practice
for i in range(len(list_of_fruits)):
    fruit = list_of_fruits[i]
    process_fruit(fruit)

# good practice
for fruit in list_of_fruits:
    process_fruit(fruit)
Enter fullscreen mode Exit fullscreen mode

9. Indexing/Counting during iteration

# Don't do this:
index = 0
for value in collection:
    print(index, value)
    index += 1


# Nor this:
for index in range(len(collection)):
    value = collection[index]
    print(index, value)

# Definitely don't do this:
index = 0
while index < len(collection):
    value = collection[index]
    print(index, value)
    index += 1

# Instead, use `enumerate()`
for index, value in enumerate(collection):
    print(index, value)
Enter fullscreen mode Exit fullscreen mode

10. Using context managers

Python provides context managers that manage the overhead of initializing and clearing up the resources and let
you focus on the implementation. For example in the case of reading a file, you don't need to be concerned
to close the file manually.

d = {"foo": 1}

# bad practice 
f = open("./data.csv", "wb")
f.write("some data")

v = d["bar"] # KeyError
# f.close() never executes which leads to memory issues

f.close()

# good practice
with open("./data.csv", "wb") as f:
    f.write("some data")
    v = d["bar"]
# python still executes f.close() even if the KeyError exception occurs
Enter fullscreen mode Exit fullscreen mode

11. Using set for searching instead of a list

s = set(['s', 'p', 'a', 'm'])
l = ['s', 'p', 'a', 'm']

# ok for small no. of elements
def lookup_list(l):
return 's' in l # O(n)


# better for large no. of elements
def lookup_set(s):
return 's' in s # O(1)
Enter fullscreen mode Exit fullscreen mode

Sets are implemented using hash in python, which makes searching of element faster(O(1)) as compared to searching in a
list(O(n)).

12. using * while importing a module

Imports should always be specific. Importing * from a module is a very bad practice that pollutes the namespace.

# bad practice 
from math import *
x = ceil(x)

# good practice 
from math import ceil   
x = ceil(x) # we know where ceil comes from
Enter fullscreen mode Exit fullscreen mode

13. using items() for iterating a dictionary


d = {
     "name": "Aarya", 
     "age": 13
 }

# Dont do this
for key in d:
    print(f"{key} = {d[key]}")

# Instead do this
for key,val in d.items():
    print(f"{key} = {val}")
Enter fullscreen mode Exit fullscreen mode

Sources

More Articles You May Like

💖 💪 🙅 🚩
dollardhingra
Dollar Dhingra

Posted on December 11, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related