Are new Python devs forgetting the Zen of Python: "There should be one—and preferably only one—obvious way to do it"?

Is it? I suspect it’s one of the most common.

Sure, but Vicente then talks about “a complex project w/ many programmers working on it”. That’s not beginners.

The OP implies that L[::-1] should not be used in code because they consider it “less intuitive”. If you have learned how general slicing syntax works then this is a pattern that you can interpret and more likely will just recognise after having seen it once. I don’t see any reason not to use this just because someone new to the language might not yet know what it means.

I often see code that I would have written with backwards slice e.g. many of these. There is even a ruff rule whose suggested fix L.reverse() I actually disagree with: in-place mutations can make the code much harder to understand even for people who do know the language basics.

Thanks for opening the interesting discussion!

I think Python is like English.

There are myriad ways of saying something to make a particular point and the language is always evolving over the course of time; some words are now archaic and hardly heard anymore while new words and phrases appear and are popularised.

People will use the communication style that best fits the situation. For me that’s the essence of the Zen quote.

If you ever want to reverse a string, then the slice notation is the obvious choice.

Of course, it won’t properly handle strings that contain combining Unicode codepoints, but, then, neither will reversed!

As Guido’s original human oracle (I wrote the poem), that’s a vital point. It wasn’t an easy job :wink:. One of his favorite quotes was Emerson’s

So it’s even more puzzling than it seems. For example, the meaning of “one obvious” also changes over time! So, with more words, the aphorism “should be” prefixed by “At any given time,”.

A finger pointing at the moon is never the moon itself.

Today, in most cases, reversed() is “the one obvious” way to do it. But didn’t used to be. reversed() is a relatively new addition, satisfying a need that came up so often not met by the more cryptic [::-1] (which was indeed obvious only if yoiu’re Dutch) that it earned a place in the builtins.

More dramatic is string formatting. There are many ways to do that. But it took decades for f-strings to be invented, which are usually the one obvious way today..

That’s progress. But for backward compatibility, all the older former one-obvious-ways persist. So the “preferably only one” qualifier was always predestined to become ever more exception than rule. Which I knew at the time, but the poem contains nothing of what I thought - it was only my best attempt at putting Guido’s ineffable thoughts into human language :wink:

Enjoy the diversity instead? But lead by example, sticking to spellings that don’t resemble puzzles. For a prime example, the former builtin reduce() was exiled to the functools module for Python 3. Nothing wrong with it, and is “the obvious way” in functional languages, but a simple explicit loop was - and remains - Python’s one obvious way.

For the proliferation of web frameworks, it’s natural that there are so many of them because web framework means so many different things. It can be a high level framework with pluggable themes, builtin database integration and so many Python interfaces for HTML widgets that the user rarely sees any raw HTML, js or CSS. Or a user might be happy generating their own HTML but wants to attach it to responses without dealing with boring HTTP stuff like Content-Length headers and optional gzip compression. Or they might want to write HTTP without a framework guessing what they want and ultimately getting in the way. Some people detest boilerplate but others prefer to feel like they’re writing a Python application using $webframework rather than writing a $webframework application that happens to use Python syntax and would therefore much prefer the boilerplate to the global singletons, decorators and custom entry points that replace it.

In end-user application packaging land, we have a similar situation in that “end-user” [1] , “application”[2] and “package”[3] all mean different things to different people but we have the opposite problem in that there isn’t enough of a range of tools to meet all those different needs so we have to work with people using the wrong tools to solve the wrong problems for the wrong reasons. It sucks. :slightly_frowning_face:


  1. Python user? Non-Python developer? No software experience at all? Favours security or convenience? ↩︎

  2. CLI/GUI/website? Requires tightly controlled dependencies? Requires modular updates? Is extendable? Requires system packages or OS integration? Is long living? May be ran as a service? ↩︎

  3. where users who only use one OS naively strive for symmetry across OSs instead of the differing native user experiences that work well on each OS ↩︎

Or HTML is completely irrelevant, and you’re building an API that returns JSON. That’s what FastAPI is for. IMO it is serving a completely different purpose to, say, Django, and yet both of them can be considered to be “web frameworks”.

And then there’s Zope, whose primary architect (Jim Fulton) said was a framework for building web frameworks. The importance of Zope (and Jim) to Python’s early days can’t be overstated. Alas, Zope never achieved the critical mass of traction it (IMO) deserved, and the company eventually gave up (voluntarily dissolving and transferring its assets to the Plone Foundation).

… if you know English.

I wonder what it’s like for someone who doesn’t. I can imagine the slice syntax being easier for them then.

This is quite different from the original, and both are obvious ways of doing two different things. Try writing down what each of them does.

Using your logic, these non-English programmers wouldn’t understand how to use Python keywords like “except, try, and, or, while, etc.”

Indeed, there can be any number of non-obvious ways, and there always
will – any Turing-complete programming language permits infinitely many
ways of doing anything.

Also note that L[::-1] isn’t something that was added to provide an
alternative less-obvious way of doing reversed(). It’s just a special
case of the general slicing mechanism that happens to have the same effect.

I believe that Stefan’s point (he may correct me if I’m wrong) is that “intuitive” and “easy to comprehend” are relative. If English is your second or third language, it may take active effort to remember what the word “reversed” means.

Many people learn to program at the same time that they are improving their knowledge of English, so they know what except, for, and while mean because they have learned Python.

Cultural and linguistic background is just one of the many ways in which the Python community – and broader community of programmers – is diverse. So, in keeping with the whole thread, there’s benefit in embracing that diversity. You might learn where you have blind spots and unchallenged assumptions.

I’m surprised very few here understand the importance of simplicity, directness, and elegance in coding. I remember before when some Apple engineers were pitching the user interface of the DVD/CD burning software to Steve Jobs and they had all these menus, buttons, checkboxes, etc. at the home screen. After the presentation, Steve Jobs walked over to the white board, drew a square to represent the main window of the program, then one button at the button that said ‘Record.’ He said that’s the first thing the user should see so they know exactly what to do and would actually want to use the app.

Software devs sometimes get enthralled in complexity and “options” and the different ways of doing things they forget simplicity, ease-of-use, intuitiveness, so they need to learn to look at it from a beginner’s mind. Complicated software rarely succeed. People will rarely use something that has a steep learning curve. They gravitate to simplicity, ease-of-use.

They want something that even at first look makes sense.

I’m not sure where you see any indication that any participants in this conversation don’t consider simplicity important. (“Elegance” is a word I avoid instinctively, since it means wildly different things to different people.)

But people with an enormous breadth and depth of experience are chiming in to note both

  • the ways in which having various ways of doing things is beneficial
  • that having various options – often “old” and “new” – is inevitable

You can close your mind to these responses. So far that seems to be the case. But I still hold out hope that you can see that the world is bigger than you realized. It can make you a better developer, if you let it.

You can keep using % formatting and optparse if you want. But all the cool kids are playing with f-strings and this new module in the stdlib called “argparse”. You should check it out.

Yeah, but is that relevant here?

I don’t think Python is complicated, and as far as I know, it is very successful.

We all understand it. Yes, there is a downside to a proliferation of options. There is also an upside. But most importantly: it’s not possible to stop it.

I’ll ask again: what do you want us (the Python community, or the core team, or the PSF) to do?

Discourage any Python development that pulls it towards complexity, redundancy, steeper-learning-curves, deterioration of Python to the point that it’s no longer consistent, recognizable. Stick to its core philosophy of “Python generally has one way of doing things.” In other words, guide it so it doesn’t turn into another platforms that is all over the place, i.e., poorly-designed crap.

Situations change over time as communities grow and culture continually reevaluates itself. We cannot anticipate everything in advance. New unanticipated needs develop as previous needs are met.

Here’s another quote from Emerson’s essay, Self Reliance:

Speak what you think now in hard words, and to-morrow speak what to-morrow thinks in hard words again, though it contradict every thing you said to-day.

The text of the essay can be found here: Wikisource: Essays: First Series/Self-Reliance. As the above quote suggests, consider the essay to be skeptical even of itself.

Your original post mentioned web application frameworks. How would we “discourage” someone from making a new framework? What if the new framework is better designed than the old one and would be a net benefit? You want fewer things, but you also want better things.

Poorly designed crap won’t get used. If we have multiple ways to do things, it’s because at a point in time a new way appeared that was competitive with the old ways. For third-party code like web frameworks, the old ways will decline in popularity and you don’t need to think about them anymore. You mentioned Django, Flask, and FastAPI. You haven’t had to think about CherryPy or Pyramid or any of the dozens of others.

F-strings are better than the other three ways to format data into strings. They were a good addition to the language. It might have been better if we had started with f-strings, and had only one way to do it, but we didn’t.

Pick any programming language that is 30 years old, and they will all demonstrate this dynamic. It’s a fact of life. Ecosystems grow organically and evolve. The Python world can’t somehow force things to be uniform, simple, and high-quality. Even closed top-down systems get duplicative and complicated with age. Look at the Windows API. It is inevitable.

Work with your collaborators to choose the way you want to do things, and strive for consistency in your projects. Advocate for the tools you think are best.

To answer your original question: no, I don’t think they are forgetting it. If I had to pick the qualities that have made Python so successful over the years, it’s that it is approachable, flexible and can be adapted to new domains. It’s an easy onramp not just for developers, but for people building tools for developers. It allows for creativity and innovation. This leads to choices and diversity, which can be complicated, but are essential for success, and most importantly, cannot be stopped.

It can be frustrating to deal with the breadth of possibilities in Python, but it’s also a sign of its success.