Categories
Tips

11 Tips And Tricks To Write Better Python Code

Here are 11 tips and tricks that will help you write better Python code and become a better programmer.

Here are 11 tips and tricks that will help you write better Python code and become a better programmer:

1. Iterate with enumerate instead or range(len(x))

In Python, we generally use a for loop to iterate over an iterable object. A for loop in Python uses collection based iteration i.e. Python assigns the next item from an iterable to the loop variable on every iteration. The usual usecase of a for loop is as follows:

values = ["a", "b", "c"]

for value in values:
  print(value)

# a
# b
# c

Now, if in addition to the value, you want to print the index as well, you can do it like this:

index = 0

for value in values:
  print(index, value)
  index += 1

# 0 a
# 1 b
# 2 c

or another common way to do this is by using range(len(x)):

for index in range(len(values)):
  value = values[index]
  print(index, value)

# 0 a
# 1 b
# 2 c

However, there is an easier and more pythonic way to iterate over iterable objects by using enumerate(). It is used in a for loop almost the same way as you use the usual way, but instead of putting the iterable object directly after in in the for loop, or putting using it as range(len(values)) , you put it inside the parentheses of enumerate() as shown below:

for count, value in enumerate(values):
  print(count, value)

# 0 a
# 1 b
# 2 c

We can also define a start argument for enumerate() as shown below :

for count, value in enumerate(values, start=1):
  print(count, value)

# 1 a
# 2 b
# 3 c

The enumerate() function gives back two variables:

  • the count of the current iteration
  • the value of the item at the current iteration

Just like the loop variables in a for loop, the loop variables can be named anything, for instance, we can call then index and value and they’ll still work. enumerate() is more efficient than a for loop as it saves you from the hassle to remember to access the value inside the loop and use it correctly and then also remember to advance the value of the loop variable, it is all handled automatically by Python.

2. Use list comprehension instead of raw for loops

List comprehension is an easier and elegant way to define an create lists based on the existing lists. They are just a single line of code consisting of brackets containing the expression that is repeatedly executed at each iteration. Hence, they are more time and space efficient than loops and transform iterative statements in a single line of code.

The usual syntax of a list comprehension looks like this:

newList = [ expression(element) for element in oldList if condition ] 

Here’s an example of list comprehension in code:

# Using list comprehension to iterate through loop
List = [character for character in 'HackerNoon']
 
# Displaying list
print(List)

# Output
# ['H', 'a', 'c', 'k', 'e', 'r', 'N', 'o', 'o', 'n']

3. Sort complex iterables with sorted()

The Python sorted() function sorts the elements of an iterable object in a specific order (ascending or descending) and returns them as a sorted list. It can be used to sort a sequence (string, tuple, list) or collection (set, dictionary, frozen set) or any other iterator.

The syntax of the sorted() function is as follows:

sorted(iterable, key=None, reverse=False)

sorted() function takes at max three parameters:

  • iterable: It could be any iterator
  • key: It is an optional argument that serves as a key for sort comparison.
  • reverse: It is also an optional argument that is used to specify a reversed sorted list as the output

4. Store unique values with Sets

A Python Set stores a single copy of the duplicate values into it. Hence, it can be used to check for unique values in a list. For example:

list_inp = [100, 75, 100, 20, 75, 12, 75, 25] 

set_res = set(list_inp) 
print("The unique elements of the input list using set():\n") 
list_res = (list(set_res))
 
for item in list_res: 
    print(item)

So the output of the above program would look like this:

The unique elements of the input list using set():

25
75
100
20
12

5. Save memory with Generators

The basic function of the generator is to evaluate the elements on demand. It is very similar to the syntax for list comprehension, where instead of square brackets, we use parentheses.

Let’s consider an example where we want to print the square of all the even numbers in a list:

myList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print("The given list is:", myList)
mygen = (element ** 2 for element in myList if element % 2 == 0)
print("Elements obtained from the generator are:")
for ele in mygen:
    print(ele)

The output of the above code would look like this:

The given list is: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Elements obtained from the generator are:
4
16
36
64
100

Having said that their syntax is quite similar to list comprehension, you must be wondering how it is different from list or set comprehension. Unlike list or set comprehension, generator comprehension does not initialize any objects. As a result, you may utilize generator comprehension instead of list or set comprehension to lower the program’s memory requirements.

6. Define default values in Dictionaries with .get() and .setdefault()

.setdefault() method allows to set dict[key]=default if key is not already in dict.

The syntax of .setdefault() looks like following:

dict.setdefault(key, default=None)

Here’s an example code snippet to understand how to use .setdefault():

a_dictionary = {"a": 1, "b": 2, "d": 4}
a_dictionary.setdefault("c", 3)

print(a_dictionary)

The output of the above code would look like:

{'a': 1, 'b': 2, 'd': 4, 'c': 3}

The same thing can also be achieved by using .get() method by passing a default value for the key, as you can see below:

a_dictionary = {"a": 1, "b": 2, "d": 4}
print(a_dictionary.get("c", 3))

print(a_dictionary)

The output of the above code would look like following:

3
{'a': 1, 'b': 2, 'd': 4}

7. Count hashable objects with collections.Counter

The Collections module supports high-performance container datatypes (in addition to the built-in types list, dict, and tuple) and contains a variety of useful data structures for storing information in memory.

A counter is a container that keeps track of the number of times equal values are added.

It may be used to implement the same algorithms that other languages employ bag or multiset data structures to implement.

Import collections makes the stuff in collections available as:

import collections

Since we are only going to use the Counter, we can simply do this:

from collections import Counter

It can be used as follows:

import collections

c = collections.Counter('abcdaab')

for letter in 'abcde':
    print '%s : %d' % (letter, c[letter])

The output of the above code would look like this:

a : 3
b : 2
c : 1
d : 1
e : 0

8. Format strings with f-Strings (Python 3.6+)

f-strings, also called as “formatted string literals“, are a new and more pythonic way to format strings, supported by Python 3.6+. They are a faster, more readable, more concise, and a less error prone way of string formatting in Python.

As the name “f-string” says, they are string literals that have an f at the beginning and curly braces containing expressions that will be replaced with their values at the runtime and then formatted using the __format__ protocol.

f-strings can be used as following:

name = "Eric"
age = 74
print(f"Hello, {name}. You are {age}.")

# 'Hello, Eric. You are 74.'

9. Concatenate strings with .join()

In Python, we can use the .join() method to concatenate a list of strings into a single string. The usual syntax for this method looks like below:

'String to insert'.join([List of strings])

It can be used in multiple ways — if you use the empty string ““, [List of strings] is simply concatenated, and if you use a comma, a comma-delimited string is created. When the newline character \n is used, a newline is appended after each string. See the example below:

l = ['aaa', 'bbb', 'ccc']

s = ''.join(l)
print(s)
# aaabbbccc

s = ','.join(l)
print(s)
# aaa,bbb,ccc

s = '-'.join(l)
print(s)
# aaa-bbb-ccc

s = '\n'.join(l)
print(s)
# aaa
# bbb
# ccc

10. Merge dictionaries with {**d1, **d2} (Python 3.5+)

The easiest way to merge dictionaries is by using the unpacking operator (**). The syntax for this method looks like this:

{**dict1, **dict2, **dict3}

Here’s an example to understand this method better:

d1 = {'k1': 1, 'k2': 2}
d2 = {'k3': 3, 'k4': 4}

print({**d1, **d2})
# {'k1': 1, 'k2': 2, 'k3': 3, 'k4': 4}

11. Simplify if-statements with if x in list

Assume we have a list with the primary colours red, green, and blue. And somewhere in our code, we have a new variable with a colour, so c = red. Then we’ll see if this is one of our primary colours. Of course, we might check this against each item on our list as follows:

colors = ["red", "green", "blue"]

c = "red"

# cumbersome and error-prone
if c == "red" or c == "green" or c == "blue":
    print("is main color")

However, this may become quite time consuming, and we can easily make mistakes, such as if we have a typo here for red. It is more simpler and far preferable to just use the expression if x in list:

colors = ["red", "green", "blue"]

c = "red"

# better:
if c in colors:
    print("is main color")

Conclusion

Python is a widely used programming language and by using the above tips and tricks, you can become a better Python programmer.

I hope this article was helpful. Keep reading!