PEP 20
The Zen of Python
In this post, let’s talk about the 19 aphorisms that define Python’s philosophy, along with simple definitions and practical examples
Easter Egg
The Zen of Python, authored by Tim Peters, is both a set of guiding principles for writing Pythonic code and a fun Easter egg hidden within Python itself.
To see Zen of Python, run either:
- Python shell
- Terminal
import this
python -c '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!
If you run into issues, it's likely that Python is not installed on your machine. Download it here.
import this
Beautiful is better than ugly
Code for humans.
Clean, readable code is easier to understand and maintain.
- ⭕ Good
def f(x):
return x*x + 2*x + 1 - ✅ Better
def quadratic(x):
return x * x + 2 * x + 1
Explicit is better than implicit
Make it obvious.
Avoid hidden meanings and ensure that the purpose of the code is obvious. Clear code is easier to understand than clever shortcuts.
- ⭕ Good
from math import * # What is being imported?
- ✅ Good
from math import sqrt, pi # Explicit and clear
Simple is better than complex
Avoid unnecessary complexity.
Complex solutions should only be used when absolutely necessary. Simplicity leads to better code.
- ❌ Complicated
def add(a, b):
return (lambda x, y: x + y)(a, b) - ✅ Simplified
def add(a, b):
return a + b
Complex is better than complicated
If complexity is necessary, structure it well.
Code should be well-structured and understandable, not convoluted or confusing.
- ❌ Complicated
def factorial(n):
return 1 if n == 0 else n * factorial(n - 1) - ✅ Complex but better
def factorial(n):
result = 1
for i in range(1, n + 1):
result *= i
return result
Flat is better than nested
Avoid deep nesting that makes code hard to follow.
Flat code is easier to read and manage.
- ⭕ Good
if user:
if user.is_active:
if user.has_permission():
print("Access granted") - ✅ Good
if user and user.is_active and user.has_permission():
print("Access granted")
Sparse is better than dense
Whitespace improves readability.
Dense code can be hard to read and understand. Spread out code with appropriate spacing.
- ⭕ Good
x=[1,2,3];y=4;z=x+y
- ✅ Good
x = [1, 2, 3]
y = 4
z = x + y
Readability counts
Code is read more often than it is written.
Prioritize readability to make it easier for others (and yourself) to understand and maintain.
- ❌ Less Readable
def d(a,b,c):
return (a+b)*c - ✅ Readable
def calculate(a, b, c):
return (a + b) * c
Special cases aren't special enough to break the rules
Consistency is key.
Stick to the rules and conventions of the language, even for special cases.
- Following the rules
def divide(a, b):
if b == 0:
raise ValueError("Cannot divide by zero")
return a / b - Breaking the rules
def divide(a, b):
if b == 0:
return None
return a / b
Although practicality beats purity
Sometimes, breaking a rule is okay for practical reasons.
While following best practices is important, practical solutions should take precedence when necessary. Using try-except
instead of checking every possible edge case:
try:
value = int(user_input)
except ValueError:
print("Invalid number")
Comparison
- Practical
def read_file(file_path):
try:
with open(file_path, 'r') as file:
return file.read()
except FileNotFoundError:
return "File not found" - Pure
def read_file(file_path):
with open(file_path, 'r') as file:
return file.read()
Errors should never pass silently
Handle errors explicitly.
Ignoring errors can lead to unexpected behavior and bugs.
- ⭕ Good
try:
risky_function()
except:
pass # Silently ignores all errors - ✅ Good
try:
risky_function()
except Exception as e:
print(f"Error: {e}")
Unless explicitly silenced
If ignoring an error is intentional, document it.
If an error must be ignored, it should be done explicitly and with good reason.
try:
os.remove("foobar.txt")
except FileNotFoundError:
pass # It's okay if the file doesn't exist
In the face of ambiguity, refuse the temptation to guess
Do not make assumptions.
Write clear logic rather than making assumptions. When code behavior is unclear, seek clarity and ensure the code's intent is explicit.
- ❌ Guessing
def get_user_age(user):
return user.get('age', 0) # Assuming age is 0 if not found - ✅ Seeking clarity
def get_user_age(user):
if 'age' in user:
return user['age']
else:
raise KeyError("User age not found")
There should be one—and preferably only one—obvious way to do it
Clear and consistent.
Python emphasizes having a single, clear way to accomplish a task, reducing confusion and increasing consistency.
- ❌ Multiple ways (Confusing)
import os
os.system("ls") # One way
import subprocess
subprocess.run(["ls"]) # Another way - ✅ Preferred
import pathlib
print(list(pathlib.Path(".").iterdir()))
Although that way may not be obvious at first unless you're Dutch
Here's why
Python might seem tricky at first, but it makes more sense once you get used to it, especially if you're familiar with its Dutch creator, Guido van Rossum.
Now is better than never
Don’t over-optimize; ship working code.
It's better to take action and write code now rather than procrastinate.
print("Launching Project...")
Although never is often better than right now
Don’t rush bad code—balance speed and quality.
Rushing to write code without proper thought can lead to poor quality. Balance urgency with careful consideration.
If the implementation is hard to explain, it's a bad idea
Code should be simple enough to explain easily.
If it's too complex to explain, it likely needs to be simplified.
- ❌ Difficult to explain
def mystery(x):
return (x & (x - 1)) == 0 - ✅ Better
def is_power_of_two(x):
return x > 0 and (x & (x - 1)) == 0
If the implementation is easy to explain, it may be a good idea
The value of simplicity and clarity in coding.
When an implementation is easy to explain, it usually means that the code is straightforward, understandable, and maintainable. Simple and clear implementations are often the best solutions.
def factorial(n):
if n == 0:
return 1
else:
return n * factorial(n-1)
Namespaces are one honking great idea—let's do more of those!
Using namespaces
Namespaces help organize code and avoid naming conflicts. Use them liberally to keep code clean and modular.
import math
print(math.sqrt(16)) # Using the math namespace to access sqrt function
Learn more!
Happy coding! 🚀