The Zen of Python is a PEP: Python Enhancement Proposals. Exactly the PEP20. This PEP contains a list of aphorisms that would help you while you are coding in Python. Long time Pythoneer Tim Peters succinctly channels the BDFL’s guiding principles for Python’s design into 20 aphorisms, only 19 of which have been written down. I will treat them in groups of 5 until the list is complete.
The easiest way to get in touch with the Zen of Python, is to try the following import call in an interactive Python shell:
Python 2.6.6 (r266:84292, Sep 15 2010, 15:52:39) [GCC 4.4.5] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> 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! >>>
Each aphorisms will lead you to the proper coding practices in Python. So, you must support your code using this philosophy and also, you must follow the Python Style Guide (PEP8). There is no custom flavours of Python styles, as the C, C++, Java and PHP has the tendency to follow. I will try to review each point of the Zen of Python.
beautiful is better than ugly
Beautiful code and algorithms have elegant constructs. For example, if we know that Python is multi-paradigm, since it can support Object Oriented, Procedural and Functional paradigms, we should find more beautiful mixing paradigms to solve certain problem, rather than doing plain paradigm problem solving. A procedural factorial function solving in Python should look similar to this one:
def factorial_procedural(n):
if n == 0: return 1
r = 1
for x in range(1, n + 1):
r = r * x
return r
The code above is ugly in Python. Yes, it’s ugly, because your are doing unnecessary steps to solve something relatively simple. The same function using a multi-paradigm approach, can be solved functionally:
def factorial_functional(n):
if n == 0: return 1
return reduce(lambda x, y: x * y, range(1, n + 1))
The code above is small, precise and elegant, in one word, it’s beautiful. That’s thanks to the Functional Paradigm supported by Python. The very basics of Python, is the fact that it supports Classes and Hierarchy for Object Oriented Programming, Control Structures for Procedural Programming and Closures and Anonymous Functions for Functional Programming. If you have available all those features, just use them, don’t stay just in one paradigm. Python have very nice ways to solve problems, it provides a wide variety of libraries and programming paradigms that are there to be used, and make your code beautiful. Probably you will find good examples of beautiful code in the book with the same name: "Beautiful Code", an excellent book.
explicit is better than implicit
Python requires some verbosity while you are coding it and descriptive names matters. For example if we have a method — called literally — f(), it does not means nothing. We must use descriptive names, and explicitly add the proper documentation to our code.
class MyClass():
def f(self, n):
if n == 0: return 1
return reduce(lambda x, y: x * y, range(1, n + 1))
The class above is cryptic. Just once you trace it, you know what it is doing. Instead, the class below is correct.
class MyMath():
"""Small Math Class"""
def __init__(self):
pass
def factorial(self, n):
""" Returns the factorial for given number n"""
if n == 0: return 1
return reduce(lambda x, y: x * y, range(1, n + 1))
It explicitly declares an empty constructor, have the proper name for the factorial function and is documented. This do not means that you can’t use certain optimizations. For example if we have a short function that do not requires an explicit else, like the following one, we just can omit that
else statement. I’ve called the max_ method, because max() is a built-in function, and also I’m using the PEP8 normative.
def max_(self, x, y):
"""Returns the maximum number between x and y"""
if x > y: return x
return y
simple is better than complex
Python is simple, Java is complex. If you add more complexity by doing strange constructs or giving the code the wrong extra lines, the code will be complex. There is a complexity metric called Cyclomatic Complexity and another one called Algorithmic Complexity. The first one is related to the code itself and number of nodes in it and the second one is related to the algorithmic complexity. In our past example, factorial_procedural() has a higher Cyclomatic Complexity than factorial_functional(). The higher is your Cyclomatic Complexity, the higher is the chance to get erroneous code, but both functions have the same algorithmic complexity. Simplicity is hard, you must think on your code, and try to omit the monkey patching behaviour.
complex is better than complicated
Probably this aphorism refers to the algorithmic complexity. If you can reduce the algorithmic complexity from a complicated algorithm to a complex algorithm, for example from quadratic complexity to linear complexity
, that will be very fine and probably you will be reducing the cyclomatic complexity too. Take the problem as simple as you can, and solve it using the simplest way, the most reduced code and the most legible code.
flat is better than nested
The reason for this is very simple. The flow control must be used on elegant manners. Nesting statements is hard to handle, not legible and leaks for clarity. For example, if we need to determine if whether or not a given list have a sequence of repeated numbers, you can solve that issue in two ways, functionally and procedural. Functionally, you will get a flat algorithm, but not using the procedural function.
def have_sequence_proc(lst):
cnt = 1
ln = len(lst)
for item in lst:
if cnt < ln:
if item == lst[cnt]:
return True
cnt += 1
return False
def have_sequence_func(lst):
return (len(filter(lambda m: m[0] == m[1],
zip(lst, lst[1:]))) > 0)
print have_sequence_proc([1, 2, 3, 4, 4, 5])
print have_sequence_proc([1, 2, 3, 4, 5])
print have_sequence_func([1, 2, 3, 4, 4, 5])
print have_sequence_func([1, 2, 3, 4, 5])
print have_sequence_func([1, 2, 3, 4, 5, 6, 7, 8])
print have_sequence_func([1, 2, 2, 3, 4, 5, 6, 7, 8])
As you can see, the first function have several nodes and variables. The second one not. The first one is more complex, instead the second function is simple and very flat. Also, if you are force to use the procedural method, you can find several examples of nested statements. The following example throws away a procedural function, that is very limited and not reusable, for a very specific use:
def test_condition_nested(n):
if (n % 2 == 0):
if (n % 3 == 0):
if (n % 4 == 0):
return True
else:
return False
else:
return False
else:
return False
def test_condition_flat(n, l):
return (len(filter(lambda x: (n % x) == 0, l)) == len(l))
print test_condition_nested(12)
print test_condition_nested(6)
print test_condition_flat(12, [2, 3, 4])
print test_condition_flat(6, [2, 3, 4])
Those are just the first five aphorisms in the Zen of Python. You can search the Internet for more comments on them, and also to take other perspectives. Try playing with Python, solving small problems and finding third party libraries that already are solving your problems.

[...] gonzalo diaz ← about the zen of python [part 1] [...]
[...] some concepts related to the Zen of Python — the aphorisms from one to five in the first part and the next five on the second part — in this article we will review the aphorisms 11 to 15. [...]