That's the cost of being a dynamic language. Since Python objects can be dynamically enhanced everywhere (also from inheriting classes and even from outside of the class) it needs dictionaries. But those can be very memory inefficient, specially on modern 64bit Hardware. One dict can easily take 1-2k for very few stored attributes (size can even depend on actual names used, because of the nature of dicts). So when it comes to millions of object instances, it is better to use __slots__ but those come with a cost: Those objects are not enhance-able any more. You have to know all attributes of the objects in advance. So you should only use it on objects that are really used a lot or are really simple.
No, this is a cost of this particular style of dynamic object model. Not all dynamic languages are dynamic in this way.
> Those objects are not enhance-able any more.
I don't see any reason why Python can't do what Clojure's defrecord does: Provide fixed fields for pre-declared slots, while still using a dictionary for extensions. It has been a while since I've used python, but I'm almost certain that there is some __special__ magic that can make this work with relative ease.
It's also worth pointing out that most modern JITs, like V8 or PyPy, can automatically detect "hidden classes" like this and optimize these objects to pack such static fields.
"modern JITs" aren't so modern at all. All that work was originally done on Smalltalk in the 1980s — it's also entirely tangential to JITing compilers, as it can easily be done with interpreters too, so it's not even a cost of this particular style of dynamic object model — it's a cost of this implementation strategy of this particular style of dynamic object model. The fact that PyPy manages fine shows it is not the language, or any model to which it subscribes, that is at fault.
I did not say, that every dynamic language has to implement it this way, but Python does. And Python was not intended to be a language for building up huge data masses in memory, though it does not so bad in most cases (leaving out the mentioned ones).
Pythons style has some advantages though. Simplicity and really a huge quantity of flexibility are two of them.
(Traditional) Python normally is not a truly compiled language -- it is just a rather simple precompilation step that makes life easier for the interpreter. When you compile or "JIT" the code, you have more options. You see the whole program. The precompiler of Python does not! It just sees the local module. So, it can not find all classes that might enhance a base class.
If you have any ideas, how to implement a better language, why don't you implement your own? It's up to you! (I guess, creating new (more or less useful) programming languages is the hobby of computer scientists anyhow)
--
I'm working on a Ruby compiler and have taken pretty much [the PyPy] approach [of automatically using slots when possible]: Any instance variable names I can statically determine are candidates for the equivalent treatment (allocating a slot at a fixed offset in the object structure).
Anything else will still go in a dictionary. In practice my experience is that a huge proportion of objects will have a fairly static set of attributes, and the dynamic set is often small enough that having pointers them included in every instance is still often cheaper than using dictionaries.
---
In a static language, your options are generally to either statically allocate slots, or explicitly use a dictionary anyway.
You are right. But the normal application of Python is in circumstances, where you are not under such pressure anyway and flexibility and ease of use is more a requirement than having maximum speed or minimal memory requirements. And of course it is particularly the CPython implementation that I described ... but CPython is still the implementation that is used most and the one where most enhancements, libraries and so exist. Other implementations might do better in many ways, but what made Python great, is still available in its original form, the CPython environment.