* It uses an interpreter, which is slower than compiled code
* All objects carry a dict to contain arbitrary attributes - this creates huge overhead
* Even when the dict is suppressed with __slots__, all containers (all classes, even!) are untyped, so extracting any field causes dynamic dispatch
* Objects cannot be stored inline in containers
* Integers are variable-sized, and thus slower.
Of course, you might counter that one could simply make a version of Python which is compiled, where all classes have a well-defined typed layout, where some classes can be immutable for performance, containers are typed, integers are machine integers, etc. But then I'd argue you're talking about a completely different language (Julia fits this description perfectly)
All my points above are about the language semantics of Python, not the implementation. Some of them may be optimized some of the time with a clever enough JIT - but only a few of these points. That's why PyPy is not as fast as C.
PyPy very much can handle all of the above cases! You should check out some of their recent papers about unboxing fields in objects. Some things are language semantics (__dict__, etc) but are often faked by proxy objects since most people don't actually care about the dict.
And despite all of this, Python has generated billions (trillions?) of value, and continues to do so.
Perhaps it's you who is focussed on the wrong things? Maybe some of these issues can be improved over time? Maybe none of those things actually matter in the real world, outside of niche use cases?
Are you arguing about whether Python is a good language or whether it's a slow language? The former is a matter of taste, the latter is objectively true. And there are good reasons to believe it will remain true.
It's created billions of dollars in value, sure. So had JavaScript and PHP. Doesn't mean they're good languages. Mediocrity gets you far, if you're at the right place at the right time.
* It uses an interpreter, which is slower than compiled code
* All objects carry a dict to contain arbitrary attributes - this creates huge overhead
* Even when the dict is suppressed with __slots__, all containers (all classes, even!) are untyped, so extracting any field causes dynamic dispatch
* Objects cannot be stored inline in containers
* Integers are variable-sized, and thus slower.
Of course, you might counter that one could simply make a version of Python which is compiled, where all classes have a well-defined typed layout, where some classes can be immutable for performance, containers are typed, integers are machine integers, etc. But then I'd argue you're talking about a completely different language (Julia fits this description perfectly)