For many of these things indeed it is about the internal implementation and not about the language itself (although the language itself has many features limiting optimizations as well).
The main problem is that modules are compiled against the CPython
implementation and the CPython API. These inefficiencies can never be fixed without changing the CPython API. However, changing that API means breaking all the modules that are compiled against that API.
This is also the reason why other interpreters besides the CPython one have so much trouble supporting all modules. They basically need to either rewrite the module code or support the (very inefficient) CPython API.
They could have changed the API to allow for much more efficient Python programs when they made the breaking transition of Python 2 to Python 3. However, instead they changed only a very small part of the API (the strings/unicode part) and left everything else intact. This meant it was easier to change code to support Python 3, however, it also means the actual benefits of switching to Python 3 are very limited while still breaking every single module that was compiled against Python 2.
This basically brings us to todays situation where billions of lines of code need to be updated to work on Python 3 (many of which will never be updated), while basically barely getting any benefits for doing so.
Yes, improved unicode support is great and I won't argue that it is an improvement, but arguing that it's worth millions of hours and millions of dollars wasted on upgrading code is a very hard sell.
Breaking backwards compatibility is very, very dangerous for popular projects, and it is something that should be taken extremely seriously. The team behind the Python 2 to Python 3 transition clearly did not do that, and the entire Python community has paid the price for that. The "print x" thing makes it extremely obvious that they did not realize the huge impact of their decision to break backwards compatibility. It is a minor thing that fixes a problem that really wasn't there to begin with, but it's a minor thing that breaks almost every single Python 2 program ever written. It's just ridiculous.
The main problem is that modules are compiled against the CPython implementation and the CPython API. These inefficiencies can never be fixed without changing the CPython API. However, changing that API means breaking all the modules that are compiled against that API.
This is also the reason why other interpreters besides the CPython one have so much trouble supporting all modules. They basically need to either rewrite the module code or support the (very inefficient) CPython API.
They could have changed the API to allow for much more efficient Python programs when they made the breaking transition of Python 2 to Python 3. However, instead they changed only a very small part of the API (the strings/unicode part) and left everything else intact. This meant it was easier to change code to support Python 3, however, it also means the actual benefits of switching to Python 3 are very limited while still breaking every single module that was compiled against Python 2.
This basically brings us to todays situation where billions of lines of code need to be updated to work on Python 3 (many of which will never be updated), while basically barely getting any benefits for doing so.
Yes, improved unicode support is great and I won't argue that it is an improvement, but arguing that it's worth millions of hours and millions of dollars wasted on upgrading code is a very hard sell.
Breaking backwards compatibility is very, very dangerous for popular projects, and it is something that should be taken extremely seriously. The team behind the Python 2 to Python 3 transition clearly did not do that, and the entire Python community has paid the price for that. The "print x" thing makes it extremely obvious that they did not realize the huge impact of their decision to break backwards compatibility. It is a minor thing that fixes a problem that really wasn't there to begin with, but it's a minor thing that breaks almost every single Python 2 program ever written. It's just ridiculous.