News for hackers. Stuff that matters.
Re:No-op statements syntactically valid only since Python X.Y by noobermin on Monday June 06, 2022 @02:19AM (#31637699)
One way was never going to work, ever. No real substantive platform of any kind will ever have one way to do something. May be if you're a literalist, there can sometimes be an "obvious way" to do something with emphasis on "obvious," but beyond that, the moment you have more than one library in the ecosystem that does a similar thing, you no longer can do something "one way."

I'm not sure if today that really matters though. I will admit I don't know much about Perl but Perl's death vs Python's life probably might have some influence from design choices but a lot of it just has to do with the libraries you have access to with Python. I know as a scientist, Python is the game in town, that has more to do with why I use it than design.

Re:No-op statements syntactically valid only since Python X.Y by sgk284 on Monday June 06, 2022 @03:29AM (#31638048)
The "one way" philosophy worked really well for Python for 15-20 years.

It was really only during the break-away adoption by the data science community (and other mass audiences) that started adding pressure to bloat the language. The adoption of 3rd party libraries like numpy, which are so critical to modern Python, also destroyed the community's "batteries included" philosophy.

Older Python felt a lot like using FreeBSD, where the whole system is cohesive and designed to work together, whereas modern Python feels a lot more like Linux – a bunch of disparate systems that try to work well together (in the best of times).

Both approaches have their strengths, and the language has certainly improved in some areas, but I prefer the older style.

In any case, it is fascinating to see how mainstream Python is now. Maybe this change in mindset was required for it to take over the world. We've come so far since Paul Graham cited the language as esoteric and its usage a high signal of competence (http://www.paulgraham.com/pypar.html).

Re:No-op statements syntactically valid only since Python X.Y by wheelerof4te on Monday June 06, 2022 @04:02AM (#31638211)
"The adoption of 3rd party libraries like numpy, which are so critical to modern Python, also destroyed the community's "batteries included" philosophy."

You are right and your FreeBSD vs Linux analogy really hits the target.

Thanks to the advancement of hardare and the development of libraries like Numpy, Python has moved from it's scripting niche and became a global, general purpose language.

Was that an error? If we look at the "batteries included" philosophy and the poor state of Python's package management after all these years...I'd say yes.

Re:No-op statements syntactically valid only since Python X.Y by DemocracyFTW2 on Monday June 06, 2022 @06:02AM (#31638693)
When I whined about Python's import system in another comment I completely forgot to add some snark concerning the horrible, horrible state of everything to do with Python package management system. Here again, many failed efforts over the years (setuptools, pip, ...), a terrifyingly convoluted packaging system, and bad, highly complex plans (virtualenv) to heal problems that are self-inflicted
Re:No-op statements syntactically valid only since Python X.Y by jimmaswell on Monday June 06, 2022 @04:33PM (#31645850)
I seldom use Python anymore but the few times I've used pip it's been fine. What went wrong with pip?
Re:No-op statements syntactically valid only since Python X.Y by squar1sm on Monday June 06, 2022 @05:51PM (#31646823)
Asking people to run `pip install` on anything but `poetry` is an anti-pattern to me. Ruby has had bundler for over a decade and this is the pattern that is working for them as well as npm/yarn. Npm comes with node, Cargo comes with Rust so the debate is somewhat reduced.

Since quality of life tools and other soft things are hard to prove, I'll tell my anecdata story point. I sought out any package manager experience in python. I landed on Pipenv which uses pip. It failed to solve the tree. This led me to find poetry and the reason for existing which is exactly my experience. That was 2-3 years ago.

https://github.com/python-poetry/poetry#why

Combine this with asdf and it aligns with most other languages.

  asdf + yarn/npm = javascript
  asdf + poetry = python
  asdf + bundler = ruby
  asdf + cargo = rust
  asdf + mix = elixir
  asdf + shards = crystal
  asdf + go.mod (others) = go
  asdf + composer = php
In legacy (don't break anything) mode, there's still no reason to not switch. I export `requirements.txt` with poetry just for pip legacy reasons and it works great. If I just update some scripts, I could avoid it. It's running all the time in CI, it's exercised quite a bit.

What's wrong with just using pip and requirements.txt? There's no dev section. In addition, bumping deps is not the same. I have a blog post explaining semver updates to a python dev:

https://squarism.com/2021/09/10/sciencing-out-updates/

my strong assertion: Python and Go missed it from the start. That's why it is so confusing. There's no other choice in Rust but Cargo. Rust devs are never confused on how to add a package, semver it. The answer is always Cargo. It's in the tutorial. It's in the book. It's in the culture.

I think I've heard that pip might support the pyproject spec, poetry already does. If you want scripts like npm, you can have that too with "taskipy". You don't have to.

Re:No-op statements syntactically valid only since Python X.Y by mhneu on Monday June 06, 2022 @03:50PM (#31645232)
It's really been a mistake for the Python core team to not figure out a better way of integration with numpy. I'm pretty sure back in the 2000s the numpy team was ready to do work on this.

Syntax integration would be great. It's such a hassle to learn two syntaxes and two data/object models to work with numpy -- as inevitably your code converts from Python objects <-> numpy objects at some point (singletons!), and it makes learners' lives much more difficult than needed.

Re:No-op statements syntactically valid only since Python X.Y by deepsquirrelnet on Tuesday June 07, 2022 @01:00AM (#31650062)
As I recall there were not one, but three libraries providing similar functionality — numpy, numeric and numarray. In the mid-2000s I was using all of them for various reasons. It took quite a while before numpy emerged as the defacto standard.

I wonder if there was no adoption into the language at that time as a result of fractured communities and lack of consensus.

Re:No-op statements syntactically valid only since Python X.Y by xenophonf on Monday June 06, 2022 @10:09AM (#31640705)
Perl's popularity waned because of the whole Perl 6 fiasco, which stole lots of energy from Perl 5, offered no migration path from Perl 5, and eventually evolved into a completely different language. As a result, Perl 5 development stalled, and developers went elsewhere. I personally stopped writing new Perl code around 2005-2006 after learning Python 2 in 2003-2004 (when I was doing a lot of Zope/Plone hacking).

I think Python 3 almost killed Python, too, and for the same reasons. The developers behind 2to3 saved the community, in my opinion, as did the folks who made the painful decision to publish a Python 2 end-of-life date sufficiently far enough into the future that people still using the old runtime had both a sense of urgency and plenty of time to complete their migrations. I finally made the leap to Python 3 around 2016. I'd like to claim that I jumped instead of being pushed, but the reality is that by then, people were developing new stuff I wanted badly on Python 3 exclusively.

Re:No-op statements syntactically valid only since Python X.Y by eesmith on Monday June 06, 2022 @11:40AM (#31641878)
I think "six" proved more useful than 2to3. This made it easier to support both Python 2 and Python 3 in the same code base, which (IMO) resulted in a smoother migration path.
Re:No-op statements syntactically valid only since Python X.Y by xenophonf on Monday June 06, 2022 @11:59AM (#31642150)
You're absolutely right, and again, I think that reinforces how important a good migration path was to Python 3. Without that path, I think there was a real risk of Python dying off same as Perl 5.

It's sad because there was a lot I liked about Perl. I wish that community had better leadership because from my quick glance at the Wikipedia page, it looks like the Perl 7 project is making the same mistakes as Perl 6/Raku did. It's really too bad.

Re:No-op statements syntactically valid only since Python X.Y by at_a_remove on Monday June 06, 2022 @12:57PM (#31642898)
Perl's popularity was already in a nosedive by that point. I was programming in Perl much prior, was on numerous mailing lists, etc. The dropoff was startling.

Frankly, I believe the terrible state of affairs on CPAN was part of the problem, but it was initiated by the "there's more than one way to do it" mentality. If I wanted to do something where it would be a good idea to have a library for that task, I would have to search many candidates, each of which did sixty to eighty percent of whatever, then see which were long-abandoned, did what they actually managed to write match what I needed, etc.

Re:No-op statements syntactically valid only since Python X.Y by marcosdumay on Monday June 06, 2022 @10:53AM (#31641257)
> but a lot of it just has to do with the libraries you have access to with Python

Certainly not. Perl was always the language that had all the libraries. Python only started to get a large ecosystem way after Perl was doomed.

Re:No-op statements syntactically valid only since Python X.Y by eesmith on Monday June 06, 2022 @03:51AM (#31638155)
I view that section as a commentary about the concept of "orthogonally", arising from Algol 68. Quoting van Wijngaarden:

> The number of independent primitive concepts has been minimized in order that the language be easy to describe, to learn, and to implement. On the other hand, these concepts have been applied “orthogonally” in order to maximize the expressive power of the language while trying to avoid deleterious superfluities

Viewing through this lens, the Python Zen's "obvious way" refers to concepts in the language, and not the wider ecosystem which includes libraries.

Re:No-op statements syntactically valid only since Python X.Y by usr1106 on Monday June 06, 2022 @08:47AM (#31639782)
> refers to concepts in the language, and not the wider ecosystem which includes libraries.

Sure, but tests in the submission (not talking about further discussions) are only about the language. And with so much new syntax added over the years I doubt that there can be only one obvious way for many problems.

"I doubt" is just my feeling. I have not make any efforts to demonstrate this by examples. And it wouldn't be easy for me because I am not very fluent with many of the newer features of the language.

Re:No-op statements syntactically valid only since Python X.Y by eesmith on Monday June 06, 2022 @11:36AM (#31641833)
While the tests are about the language, noobermin's comment that I replied to was not.

Here's my summary of the tests:

2.4: generator comprehensions; the obvious way if that's what you need

2.5: if-else expressions; a bit too easily used when if/else statement is more appropriate, but there are times where it's a good fit.

2.7: set notation: {0} is the obvious improvement over set([0])

3.0: ... as a token - I don't really understand why Python changed here. I only use it in indexing. It's not obvious when I would use it at all.

3.1: multiple context managers; the obvious improvement over a multiple indented managers

3.3: yield from list; the obvious improvement over for x in lst: yield lst

3.5: @ operator added for matrix multiplier. Solves a special pain point. Obvious only for that case.

3.6: underscores in numbers. Generally better for larger numbers. Mostly obvious.

3.7: async - I've not done async in Python yet, so can't judge

3.8: x:=expr; the debate that broke van Rossum. Not going there.

3.9: allow more complicated @annotation expressions; more useful than the alternative if that's what you need

3.10: match; no experience with it. I suspect it's more obvious

3.11: more async that I can't judge.

Re:No-op statements syntactically valid only since Python X.Y by anderskaseorg on Monday June 06, 2022 @03:08PM (#31644529)
async/await was actually added in 3.5 (although the @ test in since-3.5.py is shorter). The specific change used by since-3.7.py is that await is now allowed inside an f-string (inside an async function). The specific change used by since-3.11.py is that an async comprehension is now allowed inside a normal comprehension (inside an async function). These changes are, of course, not new primitives—just fixes to allow existing primitives to be combined in ways that should intuitively work.
Re:No-op statements syntactically valid only since Python X.Y by zbentley on Monday June 06, 2022 @11:59AM (#31642139)
For "yield from lst" I think your example should be "for x in lst: yield x".
Re:No-op statements syntactically valid only since Python X.Y by eesmith on Monday June 06, 2022 @02:46PM (#31644148)
Indeed. Thanks!
Re:No-op statements syntactically valid only since Python X.Y by jwilk on Monday June 06, 2022 @01:55PM (#31643555)
You missed 2.6: b-strings
Re:No-op statements syntactically valid only since Python X.Y by eesmith on Monday June 06, 2022 @02:45PM (#31644145)
Yes. Needed for Python 3 compatibility, where it's the "obvious" way to store a binary string.
Re:No-op statements syntactically valid only since Python X.Y by WaxProlix on Monday June 06, 2022 @02:21AM (#31637712)
The mantra was one - and only one - obvious way to do something.

So, there can and should be lots of ways to do things. But always one obvious way, a Happy Path that's not obscured at all or whatever.

Re:No-op statements syntactically valid only since Python X.Y by chrisoverzero on Monday June 06, 2022 @09:20AM (#31640094)
Let’s all stop half-remembering this quote and get it straight from the source:

> 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.

Re:No-op statements syntactically valid only since Python X.Y by cgriswald on Monday June 06, 2022 @01:47PM (#31643463)
All-in-all I think Python has done a remarkably good job at living up to that quote, with three caveats:

The first is that I think actually achieving a hard-mode form of that quote and maintaining it through the lifetime of the language is impossible in practice and theory. (Even "mostly" living up to the quote is an achievement.)

The second is that I am unsure about the obvious qualifier. Certainly I can recognize pythonic and non-pythonic constructs in python; but whether the difference is actually obvious or just a result of experience combining with community consensus I can't say.

The third is that I don't think the language is Pareto efficient between readability and most other variables. For instance, I've had code criticized as non-pythonic that was just as readable as the offered pythonic version, but had greater run-time efficiency. (To be fair, this is only an issue if you define the 'pythonic' way to be the 'one obvious way'.)

Re:No-op statements syntactically valid only since Python X.Y by PeterisP on Monday June 06, 2022 @02:25AM (#31637737)
Your comment about libraries is quite relevant still - it's about an ideological preference where you preferably would not have many libraries in the ecosystem that do a similar thing without one of them being the default obvious one way to do it. "Batteries included" philosophy is one aspect to ensure that this happens, preferring to have a 'blessed' way to everyone choosing a different library which gets the advantage of each being slightly better tailored for the need at the (significant!) cost of fragmentation and thus readability and maintenance.
Re:No-op statements syntactically valid only since Python X.Y by Scarblac on Monday June 06, 2022 @03:11AM (#31637963)
Numpy is the library that absolutely everything uses for array data. It's not part of the standard library but still.

All the other things built on top that people use Python for are very interoperable because they use the same base data type.