PEP 20 - The Zen of Python
Thomas J. Kennedy
The Python language maintains a set of Python Enhancement Proposals (PEPs). If you are curious… The full index of PEPs can be accessed at https://peps.python.org/pep-0000/.
1 The Zen of Python
For the moment, we are only interested in PEP 20 - The Zen of Python.
- 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!
Reproduced from https://peps.python.org/pep-0020/.
2 What do the Rules Mean?
A few of these rules can be discussed from the perspective of an introductory programming course (i.e., your earliest programming coursework).
-
Beautiful is better than ugly.
-
Explicit is better than implicit.
In general programming courses emphasize meaningful (or self-documenting) names for variables, functions, and classes. (While the importance of naming applies to concepts such as enumerated types and namespaces… we will forgo an exhaustive list.)
- Readability counts.
Code should not require continuous inline comments. For example…
def main():
# Point 1
x1 = 1.0
y1 = 1.0
# Point 2
x2 = 2.0
y2 = 2.0
# Compute the differences "x2 - x1" and "y2 = y1"
diff_x = x2 - x2
diff_y = y2 - y1
# Compute the distance using the euclidean distance formula
r = sqrt(diff_x ** 2 + diff_y ** 2)
# Output the distance to two (2) decimal places
print(f"The distance is {r:.2f}.")
if __name__ == "__main__":
main()
is what someone more familiar with C++
or Java
might write.
However, our focus is on Python. The Python code can be rewritten/refactored more readily based on the
- Zen of Python
rulesguidelines - Batteries Included philosophy of the Python language
Let us address both unnecessary comments (particularly regarding outputting to two decimal places and comments due to poor naming. Code along the lines of
from typing import Tuple
def point_distance(p1: Tuple[float, float], p2: Tuple[float, float]) -> float:
"""
Compute the distance between two points using the well-known euclidean
distance formula:
sqrt((x2 - x1)^2 + (y2 - y1)^2)
Args:
p1 - first point
p2 - second points
"""
diff_x = p2[0] - p1[0]
diff_y = p2[1] - p1[1]
return sqrt(diff_x ** 2 + diff_y ** 2)
def main():
# Define two points
point_1 = (1.0, 1.0)
point_2 = (2.0, 2.0)
# Compute and output the distance
distance = point_distance(point_1, point_2)
print(f"The distance is {distance:.2f}.")
if __name__ == "__main__":
main()
would be much better. These types of issues will be discussed in future lectures.
- Special cases aren’t special enough to break the rules.
- Although practicality beats purity.
Most best practice or good style discussions gloss over (or outright ignore) that programming rules are (to quote a well-known move franchise) more guidelines than actual rules.
Style rules and best practices must be applied from perspective of
Why does this rule exist?
and not rote memorization.
3 Python Includes Batteries
For many languages external libraries are usually required for common operations. However, Python includes batteries. We are interested in the first two paragraphs of the philosophy…
The Python source distribution has long maintained the philosophy of “batteries included” – having a rich and versatile standard library which is immediately available, without making the user download separate packages. This gives the Python language a head start in many projects.
However, the standard library modules aren’t always the best choices for a job. Some library modules were quick hacks (e.g.
calendar
,commands
), some were designed poorly and are now near-impossible to fix (cgi
), and some have been rendered obsolete by other, more complete modules (binascii
offers the same features as thebinhex
,uu
,base64
modules). This PEP describes a list of third-party modules that make Python more competitive for various application domains, forming the Python Advanced Library.Reproduced from https://www.python.org/dev/peps/pep-0206/#id3.
Like many Python programmers… I have made frequent use of quite a few of these built-in libraries for lecture examples and course administration (e.g., updating dates from semester to semester).
Operation | Built-in Python Module |
---|---|
Working with zip files | import zipfile |
Working with gzipped files | import gzip |
Reading, writing, or generating JSON | import json |
Converting objects to JSON | import json |
Serializing objects and data structures | import pickle |
Working with time | import time |
Working with dates and time | import datetime |
Working with SQLite | import sqlite3 |
Using advanced command line arguments | import argparse |
3.1 Third-Party (External) Libraries & pip
When external libraries are required, the Python pip
utility and a requirements.txt
can be used for all dependency and configuration management.
In C/C++ we hope for a Linux environment (or Docker). In Java… Gradle is a popular build and configuration management tool. In Rust… Cargo handles dependency and configuration management.