In-depth Introduction to the Zen of Python
The Zen of Python saw light for the first time in 1999. It's one of the many aspects that adds to the awesomeness of Python. It's a set of expressions which corners the spirit of the language. It was enounced by Tim Peters, a reputable software engineer, master Pythonista and Python's 'most prolific and tenacious core developer' in the words of none other than Guido [18]. This article bases itself mostly on the saying of core devs and highly reputable members. It makes a great gift to all those interested in the history of the sysadmin script which took the world by (pleasent) surprise.
Note: This is my first post to coderwall and i am testing the editor. I thought of sharing an article i wrote elsewhere; something true Python people will like.
Birth of the Path
The way the Zen came about was unique. It was a reflection from the unknown Patrick Phalen about the Python feel [1]:
... the more I use
and learn about the language, the more I find myself appreciating the
nice balance and heft Guido gave to it. Yet there doesn't seem to be a
single document that sums up that "aesthetic," but rather it
tends to appear piecemeal, over time, mostly in the Wisdom of Chairman Tim.
It was a call to infuse the Python spirit into aliens from Perl Land and beyond. It requested some 10 to 20 lines which sums up the Python view
Would both Guido and TIm Peters be willing to collaborate on a short
paper -- call it "The Python Way" for lack of a better title -- which
sets out the 10-20 prescriptives they might offer to those who come to
Python from other languages and immediately want to find a way to bend
it into uncomfortable positions -- (implement closures, etc.).
It was a request to prevent Pythonistas from falling into the error of campaigning for changing the language. It advocated for imbuing yourself with the language's flow and change your ways and views instead of the other way round. In the original mail, it quoted Fredrik Lundh as saying "sure looks like the 'community' thinks that changing the
language is more important that using it..." [5]. Patrick clarifies:
What I have in mind is sort of a very brief Strunk-&-White-like
"Elements of Style" for Python, which suggests fundamental idiomatic
recommendations for operating within the spirit of the language. A
distillation of Python Zen is what I'm talking about -- something to go
off and contemplate when the "fix Python now" decibels become a bit
much.
Zen, Strunk and White
The Zen school lays out hints and guidelines. You understand by your own exercise and by the company of someone seasoned in the craft
it de-emphasizes mere knowledge of sutras and doctrine and favors direct understanding through spiritual practice and interaction with an accomplished teacher or Master.[2]
The Zen was a request to help Python people achieve the Python state of mind so that your code resonates well with the structure behind, conveying in the process the associated beauty, elegance and finesse. Those guidelines if well impregnated would make your code revered whithin the circle of true monks.
But, curiously enough, Tim tells [19]:
If I were to change anything, I'd drop the reference to "Zen". That wasn't
part of the original, and was added by someone else.
In other words, the title is not from the author [23]
Strunk & White is the name of two people, viz William Strunk and Elwyn Brooks White. Strunk wrote The Elements of Style, acclaimed by the Times as one of the most influencial books since 1923 [3]. White who was Strunk's student and reviser after the professor's death describes the book as:
a forty-three page summation of the case
for cleanliness, accuracy, and brevity in the use of English [4]
The effect of the book is described below, he being Strunk:
he omitted so
many needless words, and omitted them so forcibly and with such eagerness and obvious
relish, that he often seemed in the position of having shortchanged himself — a man left
with nothing more to say yet with time to fill, a radio prophet who had out-distanced the
clock. Will Strunk got out of this predicament by a simple trick: he uttered every sentence
three times
One effect of applying the Zen would then also be lighter code files.
The Master Showers his Blessings
Master Tim heard the plea, approved the demand and responded accordingly [6]
Clearly a job for Guido alone -- although I doubt it's one he'll take on
(fwiw, I wish he would too!). Here's the outline he would start from,
though <wink>:
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!
The 20th was left for Guido to fill in:
There you go: 20 Pythonic Fec^H^H^HTheses on the nose, counting the one I'm
leaving for Guido to fill in.
Venerable Tim shares exactly how the lines came about [15]:
It was a throwaway python-list post. But like all great triumphs of literature, it was written during commercials breaks while watching professional wrestling on TV, and munching on a ham sandwich. All true!
Yet, the author is emphatical: It's complete and more than meets the demand [6]:
If the answer to any Python design issue
isn't obvious after reading those -- well, I just give up <wink>.
The above also reveals the purpose of the Zen: To address design issues. And it's not a simple matter. Guido says [18]:
In many ways, the design philosophy I used when creating Python is probably one of the main reasons for its ultimate success.
The Zen only gives the outlines, in contrast to Strunk and White which gives explanations and examples in addition. Thus the need for commentaries. These help the non-initiated without being a replacement for the company of the bright minds.
In a time of fluctuating and steered standards, the reference in the actual PEP8 document to Strunk and White in the usage of the English language caused a bitter, ugly and messy thread [7]. It caused some of the best people of the community to forego following python-list [8], a casual reminder that being too open without limit hurts.
Reality of the Zen
The Zen has become an important piece of the Python programming language. If you don't know the Zen, you won't strike the right chord to communicate with the community. Raymond Hettinger advises:
Before creating more tracker items, please take time to learn about how Python's history, how it is used, and its cultural norms. In particular, read the Zen of Python, consider what is meant by duck-typing, what is meant by "a consenting adults language", what is meant by over-specification, etc. Python is quite different from Java in this regard. [13]
There's also a practical aspect to it. It's popular because it works [14]. It's the golden guiding principle in pretty much everything Python.
Finally are the Zen points rules? What are they really. Many people take the Zen for rules. The 'most opinionated linter ever' at one time actually included the Zen to back their views [9]. It was situations like these which prompted me to write: The Zen Of Python Is A Joke And Here Is Why [10]. It was nice enough for Michael Kennedy and Brian Okken to call it a 'must read' on PythonBytes [11].
According to Nick Coghlan, the Zen gives you the idea, not everything [12]:
This
challenge is reflected in the fact that the Zen of Python is
deliberately self-contradictory, as it articulates competing design
principles to take into consideration, rather than being able to
provide ironclad rules that avoid the need for human judgement in
determining which of those design guidelines are most salient in any
given situation.
Self contradiction is also coincidentally, one of the criticised aspect of Strunk and White [17].
The Zen also goes beyond coding, such as shaping the thought pattern of features [12]:
The thing we work toward as core developers, and aspiring core
developers, is good design intuition that aligns with the Zen of
Python. That doesn't mean we're all going to be able to perfectly
articulate that intuition in every case, and even when we can, those
explanations are themselves generally going to be backed by intuition
rather than rigorous scientific research.
If ever i myself would have added a 20th one it would have been: "Use your judgement.". But Nick illustrated it better.
As for the famous import this
command, it was Barry Warsaw's pick. He sneaked it in a this.py in 2001 along with the ROT13 obfuscation [16]. He also mentionned that it was a time 'when the Python community had a sense of humor'.
Commentary
Now the time is ripe to see what the Zen actually means. But before we should know that whatever the words
and concepts mean in the Zen is not necessarily applicable elsewhere [20].
Beautiful is better than ugly.
Beautiful and ugly in this context has nothing to do with human appearance. It's in the same general sense as in other technical fields: there's beautiful & ugly physics, beautiful & ugly mathematics, beautiful & ugly computer code [19]. Beauty in design is very similar to beauty in flora. For it refers to a general feeling of consistency, pureness and standing out on its own. It's abstract and doesn't have anything to do with humans [20]. This line can be replaced by 'Elegant is better than inelegant.' to understand it better [21]. The 'beauty' line is one of multiple contrasts, and should be judged in that context, not in isolation [22]. At heart, Python's design emerged from Guido's sense of beauty [23]
Explicit is better than implicit.
The Zen of Python points out that "explicit is better than implicit" for a reason: ambiguity and implicit knowledge that is not easily communicated code is easy to get wrong and leads to bugs. By forcing developers to explicitly separate out their binary data and textual data it leads to better code that has less of a chance to have a certain class of bug.
Brett Cannon [25]
It's been interesting seeing how ppl interpret "explicit is better than implicit" to say specifying 'object' is good. For me, syntactically leaving out a base class is explicit, not as verbose, and is more visually identifiable
Brett Cannon [26]
Implicit package directories go against the Zen of Python
Getting this one out of the way first. As I see it, implicit package
directories violate at least 4 of the design principles in the Zen:
- Explicit is better than implicit (my calling them implicit package
directories is a deliberate rhetorical ploy to harp on this point,
although it's also an accurate name)
- If the implementation is hard to explain, it's a bad idea (see the
section about backwards compatibility challenges)
- Readability counts (see the section about introducing ambiguity into
filesystem layouts)
- Errors should never pass silently (see the section about implicit
relative imports from main)
Nick Coghlan [24]:
Simple is better than complex.
Currently, when I teach sets, I take pleasure in the near-zero learning curve
and absence of special cases. Set code becomes a prime example of
"readability counts" and "simple is better than complex." More importantly,
I think there is value in API simplicity for lists, sets, and dicts, our basic tools.
The ABCs for sets currently reflect that simplicity and it would be sad if that
started to get lost in order to save one line here or there.
Raymond Hettinger [39]
Complex is better than complicated.
oxfordlearnersdictionaries.com gives both complex and complicated as synonyms with meaning:
"made of many different things or parts that are connected; difficult to understand"
dictionary.cambridge.org gives complex as: "having many parts connected in ways that are difficult to understand" and complicated as: "confusing or difficult to understand"
macmillandictionary.com defines complex as: "something that is complex has a lot of details or small parts that make it difficult to understand or deal with" and complicated as: "difficult to do, deal with, or understand, especially because of involving a lot of different processes or aspects" and 2. "made up of many different but connected parts"
merriam-webster.com gives complex as: a whole made up of complicated or interrelated parts and composed of two or more parts, complicated as: consisting of parts intricately combined and difficult to analyze, understand, or explain
We can translate the line to mean:
A solution which is made up of different interconnected parts is better than one which is difficult to analyze, understand, or explain
or
A complex solution is better than a more complex one
or
A solution which is made up of different interconnected parts is better than one which has many parts but is difficult to analyze, understand, or explain
Flat is better than nested.
Nesting constructs like conditionals or functions or classes or modules one inside the other too much is frowned upon. The x.y.z.q.w.w example is given as the author of the lib nested too many modules one inside the other, given a tiring usage experience
Sparse is better than dense.
When I channeled "sparse is better than dense" as one of Guido's
fundamental design principles, I was as mystified as anyone else. Indeed,
my first thought was "what the hell is that supposed to mean?!". But, as a
professional channeler, I was duty-bound to pass it on as it was revealed,
neither adding nor removing jot nor tittle.In the years since, I've come to see that it has many meanings, some of
which I explained yesterday. I'm learning from other thoughtful posts (such
as yours) that I still have a long way to go in mining its full depth. Or
in realizing its full shallowness, depending on how you view it <wink>.<< Or maybe his attention is just elsewhere... but I'd like to think that
this is a Zen koan.>>Oh no. Koans are far more advanced, in the nature of using a stick to stir
up a fire that consumes the stick in its quest to illuminate its own nature.
The channeled 20 Pythonic Theses (their original name -- "The Zen of Python"
was tacked on by somebody else, whom I suspect was not really a Zen master)
are more about using sticks to build a strong platform, as if sticks were
real and strong platforms were worthy of building. It takes a stronger
channeler than me to dismiss that as illusion. The end of Pythonic
Enlightenment is pleasure in achieving fine code; it's not enough to get you
Nirvana, presumably because it's still full of sticks <wink>.<<Unlike most of the other people in this thread, I always thought of
sparse v. dense as a syntactic/semantic issue.>>That's definitely part of it. The openness of Python's visual appearance,
the ubiquitous use of dicts, and the carefully chosen handful of control
structures were the first things I thought of.<<...
I'm probably reading more into this little statement than is there.>>I don't believe that's possible. Try harder <wink>.
Tim Peters [40]
Readability counts.
There's that word "readability" again. Sometimes I wish the Zen of
Python didn't use it, because everyone seems to think that "readable"
means "code I like".
Chris Angelico [34]
The motto of Python is clarity. The language attempts to be as readable as the english language. Guido says [18]:
I’d like to mention one readability rule specifically: punctuation characters should be used conservatively, in line with their common use in written English or high-school algebra.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
if you're going from 8-bit strings to unicode using implicit con-
version, the current design can give you:"UnicodeError: UTF-8 decoding error: unexpected code byte"
if you go from unicode to 8-bit strings, you'll never get an error.
however, the result is not always a string -- if the unicode string
happened to contain any characters larger than 127, the result
is a binary buffer containing encoded data. you cannot use string
methods on it, you cannot use regular expressions on it. indexing
and slicing won't work.unlike earlier versions of Python, and unlike unicode-aware versions of Tcl and Perl, the fundamental assumption that a string is a sequence of characters no longer holds. =20
in my proposal, going from 8-bit strings to unicode always works.
a character is a character, no matter what string type you're using.however, going from unicode to an 8-bit string may given you an
OverflowError, say:"OverflowError: unicode character too large to fit in a byte"
the important thing here is that if you don't get an exception, the
result is always a string. string methods always work. etc.[8. Special cases aren't special enough to break the rules.]
Fredrik Lundh [42]
First, I think the PyCharm case is compelling enough on its own. I
realized after I sent it that there's a related class of tools that are
interested: PyFlakes, PyLint, and the like. I'm sure the static
correctness analyzers would like to be able to automatically determine
"this is an illegal number of parameters for this function" for
builtins--particularly for third-party builtins! The fact that we
wouldn't need to special-case pydoc suggests it's the superior
approach. ("Special cases aren't special enough to break the rules.")
Larry Hastings [41]
Errors should never pass silently.
Unless explicitly silenced.
Thus, in Python 2.3, we abandoned my home-grown 2.2 MRO algorithm in favor of the academically vetted C3 algorithm. One outcome of this is that Python will now reject any inheritance hierarchy that has an inconsistent ordering of base classes. For instance, in the previous example, there is an ordering conflict between class X and Y. For class X, there is a rule that says class A should be checked before class B. However, for class Y, the rule says that class B should be checked before A. In isolation, this discrepancy is fine, but if X and Y are ever combined together in the same inheritance hierarchy for another class (such as in the definition of class Z), that class will be rejected by the C3 algorithm. This, of course, matches the Zen of Python's "errors should never pass silently" rule.
Guido [33]
This is of course a backwards-incompatible change to logging semantics: instead
of saying that logging will be silent unless explicitly asked to produce output,
we're saying that logging will always produce output for warnings and errors (or
perhaps just errors), unless explicitly silenced. This is of course in line with
the Zen of Python; the present behaviour, which is not so aligned, is based on
the idea that logging should not affect program behaviour if it's not wanted by
the program developer (as opposed to library developer).It would also mean changing the documentation about NullHandler to say: "If you
have messages which must get out when you can't raise an exception, then don't
add a NullHandler to your top-level loggers."
Vinay Sajip [28]
You might prefer to get an exception for "missing keys"that would help alert you to a bug in your
program, in cases in which you know all ks in somekeys should definitely also be keys in
somedict. Remember, "errors should never pass silently. Unless explicitly silenced," to quote The
Zen of Python --Python Cookbook
In the face of ambiguity, refuse the temptation to guess.
Well, the Zen of Python states "In the face of ambiguity, refuse the temptation
to guess". So that's the policy the builtin dict follows - it doesn't try to guess when to
make a copy, or whether or not to use identity based semantics in the face of
mutability. Instead, it raises an exception at key entry time, asking the
programmer to clarify their intent.
Nick Coghlan [37]
On the issue of {a.b.c}: like several correspondents, I don't like the
ambiguity of attribute vs. key refs much, even though it appears
useful enough in practice in web frameworks I've used. It seems to
violate the Zen of Python: "In the face of ambiguity, refuse the
temptation to guess."Unfortunately I'm pretty lukewarm about the proposal to support
{a[b].c} since b is not a variable reference but a literal string 'b'.
It is also relatively cumbersome to parse. I wish I could propose
{a+b.c} for this case but that's so arbitrary...
Guido [31]
By now, you can probably imagine why Python refuses to guess among the hundreds of possible
encodings. It's a crucial design choice, based on one of the Zen of Python principles: "In the face
of ambiguity, resist the temptation to guess." --Python Cookbook
There should be one-- and preferably only one --obvious way to do it.
But remember TOOWTDI from the Zen of Python.
Guido [32]
The Zen of Python says that "there should be one -- and preferably only one -- obvious way to do it". Having literals in the language that could represent either textual data or binary data was a problem.
Brett Cannon [25]
When Python evolves, new ways emerge inevitably. DeprecationWarning
are emitted to suggest to use the new way, but many developers ignore
these warnings which are silent by default.
Victor Stinner [35]
String formatting is one of those things that defy the
Zen of Python, that there should only be one obvious way to do things.
Mariatta Wijaya [36]
It should be noted that the dashes here don't play a role as it's Tim's way of emphasis. And it is to be noted that Brett missed it on his blog. He was maybe writing from memory.
Although that way may not be obvious at first unless you're Dutch.
In context, "Dutch" means a person from the Netherlands, or one imbued with
Dutch culture (begging forgiveness for that abuse of the word). I would
have said French, except that every French person I asked "how do you make a
shallow copy of a list?" failed to answer: alist[:]
so I guess that's not obvious to them. It must be obvious to the Dutch,
though, since it's obvious to Guido van Rossum (Python's creator, who is
Dutch), and a persistent rumor maintains that everyone who posts to
comp.lang.python is in fact also Dutch. The French people I asked about
copying a list weren't Python users, which is even more proof (as if it
needed more).Or, in other words, "obvious" is in part a learned, cultural judgment.
There's really nothing universally obvious about any computer language,
deluded proponents notwithstanding. Nevertheless, most of Python is obvious
to the Dutch. Others sometimes have to work a bit at learning the one
obvious way in Python, just as they have to work a bit at learning to
appreciate tulips, and Woody Woodpecker impersonations.
Tim Peters [38]
Now is better than never.
Although never is often better than right now.
There are also cases where we'll decide "it seems plausible that this
might be a good idea, so let's try it out and see what happens in
practice rather than continuing to speculate" - only ever doing things
that you're already 100% certain are a good idea is a recipe for
stagnation and decline (hence the "Now is better than never" line in
the Zen).
Nick Coghlan [27]
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.
Yeah, that's what everybody proposes to keep the language semantics
unchanged. But I claim that an easier solution is to say to hell with
those semantics, let's change them to make the implementation simpler.
That's from the Zen of Python: "If the implementation is easy to
explain, it may be a good idea." I guess few people can seriously
propose to change Python's semantics, that's why I am proposing it.
Guido [29]
Accepting peps: A bit more motivation for my choice: re-reading PEP 549 reminded me of how
its implementation is remarkably subtle (invoking Armin Rigo; for more
details read https://www.python.org/dev/peps/pep-0549/#implementation). On
the contrary, the implementation of PEP 562 is much simpler. With the Zen
of Python in mind, this gives a hint that it is the better idea, and
possibly even a good idea.
Guido [30]
Namespaces are one honking great idea -- let's do more of those!
Namespaces (and also global and local scopes) are key for preventing names in one module or scope from conflicting with names in another. But also remember that flat is better than nested: As great as they are, namespaces should be made only to prevent naming conflicts, and not to add needless categorization.
Al Sweigart [43]
The Koans offered the programming world a great legacy. It is an interesting sight to see from Go to JavaScript devs analysing their own langs in the light of the Zen.
Your suggestions accepted at: arj [.] python [@] gmail [.] com
[1] https://mail.python.org/pipermail/python-list/1999-June/014096.html
[2] https://en.wikipedia.org/wiki/Zen with references to Poceski and Yampolski
[3] All-TIME 100 Nonfiction Books. Time, Inc. Retrieved 2014-05-14.
[4] http://www.jlakes.org/ch/web/The-elements-of-style.pdf
[5] https://mail.python.org/pipermail/python-list/1999-June/017368.html
[6] https://mail.python.org/pipermail/python-list/1999-June/001951.html
[7] https://mail.python.org/archives/list/python-ideas@python.org/thread/AE2M7KOIQR37K3XSQW7FSV5KO4LMYHWX/
[8] https://www.mail-archive.com/python-dev@python.org/msg109166.html
[9] https://github.com/wemake-services/wemake-python-styleguide/tree/fd7b6d9d14d73cab3d7f3ac4c910e4c75b093c4c
[10] https://dev.to/abdurrahmaanj/the-zen-of-python-is-a-joke-and-here-is-why-you-should-not-take-it-too-seriously-508d
[11] https://pythonbytes.fm/episodes/show/170/visualize-this-visualizing-python-s-visualization-ecosystem
[12] https://mail.python.org/archives/list/python-dev@python.org/thread/DOKCD6TKN26DOOMYWAHFIMU3LGSCN7Y5/
[13] https://mail.python.org/pipermail/docs/2014-June/019159.html
[14] https://mail.python.org/pipermail/python-committers/2018-July/005747.html
[15] https://www.wefearchange.org/2020/05/zenofpython.rst.html
[16] https://www.wefearchange.org/2010/06/import-this-and-zen-of-python.html
[17] Wikipaedia via Pullum, Geoffrey K. (April 17, 2009). "50 Years of Stupid Grammar Advice". The Chronicle of Higher Education.
[18] http://python-history.blogspot.com/2009/01/pythons-design-philosophy.html
[19] https://mail.python.org/pipermail/python-ideas/2018-September/053389.html
[20] https://mail.python.org/pipermail/python-ideas/2018-September/053382.html
[21] https://mail.python.org/pipermail/python-ideas/2018-September/053412.html
[22] https://mail.python.org/pipermail/python-ideas/2018-September/053421.html
[23] https://groups.google.com/g/python-ideas/c/Upc9MbzmFAA/m/2TiIWTlbBwAJ
[24] https://mail.python.org/pipermail/import-sig/2012-March/000423.html
[25] https://nothingbutsnark.silvrback.com/why-python-3-exists
[26] https://twitter.com/brettsky/status/1253704411873869826?lang=en
[27] https://mail.python.org/pipermail/python-list/2005-January.txt
[28] https://mail.python.org/pipermail/python-dev/2010-December/106556.html
[29] https://mail.python.org/archives/list/python-dev@python.org/thread/XZ23MPVGDDHUWE2VTGGEHVW4A4W76SH6/
[30] https://mail.python.org/pipermail/python-dev/2017-November/150528.html
[31] https://mail.python.org/pipermail/python-dev/2006-May/065059.html
[32] https://mail.python.org/pipermail/python-3000/2006-April/000348.html
[33] http://python-history.blogspot.com/2010/06/method-resolution-order.html
[34] https://www.mail-archive.com/python-dev@python.org/msg100513.html
[35] https://discuss.python.org/t/rejected-rfc-pep-608-coordinated-python-release/2539
[36] https://static.realpython.com/python-tricks-book/Python%20Tricks%20Sample.pdf
[37] https://mail.python.org/pipermail/python-list/2005-January/296762.html
[38] https://mail.python.org/pipermail/python-list/2004-May/283635.html
[39] https://mail.python.org/pipermail/python-ideas/2009-February/002998.html
[40] https://mail.python.org/pipermail/python-list/2002-July/147124.html
[41] https://mail.python.org/pipermail/python-dev/2013-July/127229.html
[42] https://mail.python.org/pipermail/python-dev/2000-April/003742.html
[43] https://inventwithpython.com/blog/2018/08/17/the-zen-of-python-explained/