Skip to main content
HomeAbout PythonLearn Python

Lessons from the Zen of Python

Learn about the Zen of Python and discover the principles of writing clean, elegant code in Python.
May 2022  · 12 min read

What is the Zen of Python? 

The Zen of Python is a set of nineteen aphorisms that serve as guiding principles for Python’s design. It was actually supposed to be twenty aphorisms; but Guido van Rossum, the creator of Python, has still not added the final aphorism as intended by Tim Peters, the creator of the Zen of Python. Guido reportedly stated that the missing twentieth aphorism is “some bizarre Tim Peters inside joke.”

Despite the missing twentieth aphorism, the Zen of Python was standardized as PEP 20 in 2004 due to its heavy influence on Python programmers' development process. Following the Zen of Python is not compulsory, but knowing it and keeping it in mind is advised. If you ever forget the lessons, you can easily refresh your memory by running import this from the Python interpreter. 

>>> import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

In this article, we are going to cover each lesson in more detail. 

#1 Beautiful is better than ugly 

If you are a programmer, there is no doubt that you are highly skilled. The ability to solve problems with code is not an easy task, but as a Pythonista, more is expected of you. Beautiful code is better than ugly code. Python’s rapid rise to fame is partly due to its accessibility: it is simple, readable, and elegant. As a Python developer, you have a responsibility to maintain the pythonic standard by writing beautiful code. 

What is beautiful code? Well, it is subjective - beauty is in the eye of the beholder and all that jazz. A simple rule of thumb to keep you in check is to write clean, readable code that can be easily understood by other developers. For example: 

"""
Initial code was created by Vishal Sharma
See:  https://towardsdatascience.com/the-zen-of-python-a-guide-to-pythons-design-principles-93f3f76d088a
"""
def collatz(num):
    if num % 2 == 0:
        return num // 2
    else:
        return 3 * num + 1

number = input("Enter a number: ")

while number != 1:
    number = collatz(int(number))
    print(number)

"""
Enter a number: 5
16
8
4
2
1
"""

The code above works perfectly fine, but it is not necessarily beautiful. We have an unnecessary else condition in our collatz function that can be removed as follows: 

def collatz(num):
  if num % 2 == 0:
      return num // 2
 
  return 3 * num + 1

Thus, when presented with a scenario in which you have two working pieces of code, you should opt for the one that is simpler, more readable, and easier to understand. 

#2 Explicit is better than implicit

Explaining any aphorism as “self-explanatory” is a massive mistake - however, you will still see people doing it anyway. The main gist behind “explicit is better than implicit” is that verbose code is preferable to indirect code. Do all you can to ensure your code’s functionality is not hidden behind obscure language. Someone with no prior knowledge of your program should still be able to understand what is happening in your code. 

#3 Simple is better than complex

You would probably laugh if your mate pulled out a jetwash to clean the dishes after dinner. Not only is it an extremely daft solution, but there is also a high chance the plates may get damaged. In the same way, applying a highly complex solution to a simple programming problem is extremely impractical. There is no need to overcomplicate your solution, even if you think it makes you look smart. You may cause more damage than justice and it is not appreciated in Python. 

Take a look at this function that is used to reverse a string: 

def reverse_string(string):
    if len(string) == 1:
        return string
    else:
        return reverse_string(string[1:]) + string[0]


string = "kurtis"

print(reverse_string(string))

"""
sitruk
"""

The code above certainly solves the problem but it is unnecessarily complex. If you have a good grasp of Python, you know that a string can be reversed with indexing. 

string = "kurtis"

# annonymous function solution
reverse_string = lambda x: x[::-1]

# function solution
def reverse(string):
    return string[::-1]

print(reverse_string(string))
print(reverse(string))

"""
sitruk
sitruk
"""

#4 Complex is better than complicated 

Now, washing plates with a jetwash is impractical: you would be better off with a simple solution such as running tap water. But what if the problem was to clean a 4x4 Range Rover? The previous aphorism and this one remind us that both simple and complex techniques can be applied to solve one problem. Cleaning a 4x4 Range Rover is not a simple problem and trying to apply the same techniques you would use to wash your dishes may work but is more complicated than using a jetwash. Thus, you should favor simplicity over complexity, but in situations where simplicity is impractical, you are better off opting for complexity - know the limits of simplicity. 

#5 Flat is better than nested 

Programmers love to organize things into categories, subcategories, and sub-subcategories as a way to separate functionality. Although it may sound orderly, organizing code in such a manner may lead to more confusion than it does organization. 

There is nothing wrong with putting all of your code in one top-layer module: meaning you would not have to do something like from spam.foo.bar.john.doe import chicken to access a specific functionality. The more subcategories you add, the more complicated your code becomes. Do all you can to stick to a flat structure when possible.

#6 Sparse is better than dense

Programmers are considered to be among the most intelligent human beings, so there is no need to emphasize your intellect with over-elaborate hacks. The most common one you will hear is “how to do [some complicated task] in 1 line of code.” Sometimes, one-liners are justified, but avoid situations in which you compromise readability for the sake of fitting all of the functionality into one line. 

Take this piece of code as an example: 

"""
Code source Al Sweigart
See: https://inventwithpython.com/blog/author/al-sweigart.html0
"""
print('\n'.join("%i bytes = %i bits which has %i possible values." % (j, j*8, 256**j-1) for j in (1 << i for i in range(8))))
"""
1 bytes = 8 bits which has 255 possible values.
2 bytes = 16 bits which has 65535 possible values.
4 bytes = 32 bits which has 4294967295 possible values.
8 bytes = 64 bits which has 18446744073709551615 possible values.
16 bytes = 128 bits which has 340282366920938463463374607431768211455 possible values.
32 bytes = 256 bits which has 115792089237316195423570985008687907853269984665640564039457584007913129639935 possible values.
64 bytes = 512 bits which has 13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084095 possible values.
128 bytes = 1024 bits which has 179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137215 possible values.
"""

The code certainly works but it is an absolute nightmare to understand: it is cramped and hard to read. 

Let us see what the same code would look like if we wrote it as sparse code: 

# Sparse example
bytes_and_bits = {j: j*8 for j in (1 << i for i in range(8))}

for bytes, bits in bytes_and_bits.items():
    print(f"{bytes} bytes = {bits} which has {256**bytes-1} possible values")

"""
1 bytes = 8 which has 255 possible values
2 bytes = 16 which has 65535 possible values
4 bytes = 32 which has 4294967295 possible values
8 bytes = 64 which has 18446744073709551615 possible values
16 bytes = 128 which has 340282366920938463463374607431768211455 possible values
32 bytes = 256 which has 115792089237316195423570985008687907853269984665640564039457584007913129639935 possible values
64 bytes = 512 which has 13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084095 possible values
128 bytes = 1024 which has 179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137215 possible values
"""

The above code is much easier to read and does the exact same thing as the one-liner.

#7 Readability counts

If you have not guessed it already, readability counts when it comes to Python. Your job is to write the code once. However, there is a good chance it is going to be read a number of times. Taking this into account, dropping vowels from variable and function names is not a good idea: in a situation where you can name a function create_lst or create_list, choose the latter. 

#8 Special cases aren’t special enough to break the rules

Python [and programming in general] is full of a number of best practices to adhere to. It is better to follow best practices than to do it your own way since that often leads to inconsistent, unreadable code. 

#9 Although practicality beats purity

Lesson nine is an extension of lesson eight. Yes, it is better to follow best practices, but going out of your way to adhere to the rules can also result in unreadable code. Thus, each rule may have an exception. If your way of solving a problem is more practical, readable, and easier to understand, then it is better to deviate from the established best practices. 

#10 Errors should never pass silently 

A silent error is when a program returns an error code or None instead of raising an exception. It is better for a program to crash than for the error to be silenced and continue running. In the long run, silencing errors can lead to bugs in your program that are much harder to squash. 

#11 Unless explicitly silenced

Lesson eleven is an extension of lesson ten. There are some instances in which you may want to ignore errors caused by your program. In such cases, the best practice is to explicitly silence the error in your code. 

#12 In the face of ambiguity, refuse the temptation to guess

Computers do only what we tell them to do: if your code is not behaving as you would like it to, it is because it is doing what you have told it to do. Trying to fix the behavior by blindly attempting several different solutions until one works is a poor strategy - you may end up masking the problem rather than solving it. Resist the temptation. Instead, think through the logic of the problem and apply critical thinking to come up with an appropriate solution. 

#13 There should be one - and preferably only one - obvious way to do it 

The Perl programming language motto is: “There’s more than one way to do it!” Having too many options often leads to choice overload. A similar scenario occurs when there are several ways to write code that accomplish the same goal. You have more flexibility in the way you write code, but now you have to learn all the possible ways the code could have been written in order to read it: the extra work required to learn all scenarios is unnecessary. 

#14 Although that way may not be obvious at first unless you're Dutch

This aphorism is a display of Tim Peters’ sense of humor: Guido van Rossum, creator of the Python programming language and Benevolent Dictator For Life (BDFL) for Python, is Dutch. It is a joke to remind us that being able to understand and recall the language rules of Python is difficult for everyone except its creator. 

#15 Now is better than never

This aphorism tells us that code stuck in an infinite loop or code that hangs is worse than code that does not. 

#16 Although never is often better than *right* now

Continuing on from lesson sixteen: it is better to wait for your program to finish executing than to terminate it early and get incorrect results. 

#17 If the implementation is hard to explain, it’s a bad idea

It is not good enough if you are able to understand your own implementations - “I know what I’m trying to say” does not cut it. Programming is a team activity, and if you are unable to explain your implementation to your teammates, then it is very likely that you have made the solution too complicated. 

#18 If the implementation is easy to explain, it may be a good idea

However, easily explainable code does not necessarily mean it is not bad code - it just means it is easy to explain. You may still have bad code but the fact that it is easy to explain means you are on the right track. 

#19 Namespaces are one honking great idea - let’s do more of those!

A namespace is an abstraction used in Python to organize names assigned to objects in a program. When presented with a particular namespace and scope, Python is able to determine what object you are referring to when you make a call to a symbolic name. All this aphorism is saying is that the way Python organizes the symbolic names under the hood is pretty awesome. 

Conclusion 

In this article, we have presented our interpretation of the Zen of Python, guidelines created to motivate Python programmers to write clean, readable code. Whilst some look at the Zen of Python as the ultimate blueprint for seamless code writing, others take it less seriously.  We suggest you try applying the principles to your own code to see how they can improve your work firsthand.  If you'd like to learn more about writing optimized code, check out DataCamp's Writing Efficient Python Code.  

Topics

Python Courses at DataCamp 

Course

Introduction to Python

4 hr
5.5M
Master the basics of data analysis with Python in just four hours. This online course will introduce the Python interface and explore popular packages.
See DetailsRight Arrow
Start Course
See MoreRight Arrow
Related

Exploring Matplotlib Inline: A Quick Tutorial

Learn how matplotlib inline can enable you to display your data visualizations directly in a notebook quickly and easily! In this article, we cover what matplotlib inline is, how to use it, and how to pair it with other libraries to create powerful visualizations.
Amberle McKee's photo

Amberle McKee

How to Use the NumPy linspace() Function

Learn how to use the NumPy linspace() function in this quick and easy tutorial.
Adel Nehme's photo

Adel Nehme

Python Absolute Value: A Quick Tutorial

Learn how to use Python's abs function to get a number's magnitude, ignoring its sign. This guide explains finding absolute values for both real and imaginary numbers, highlighting common errors.
Amberle McKee's photo

Amberle McKee

How to Check if a File Exists in Python

Learn how to check if a file exists in Python in this simple tutorial
Adel Nehme's photo

Adel Nehme

Writing Custom Context Managers in Python

Learn the advanced aspects of resource management in Python by mastering how to write custom context managers.
Bex Tuychiev's photo

Bex Tuychiev

How to Convert a List to a String in Python

Learn how to convert a list to a string in Python in this quick tutorial.
Adel Nehme's photo

Adel Nehme

See MoreSee More