I think you mean the following paragraph of PEP (in the section section of the dictionary section ):
When resizing a split dictionary, it is converted to a combo table. If the resizing occurs as a result of saving the attribute of the instance, and there is only an instance of the class, then the dictionary will immediately crack. Since most OO codes will set attributes in the __init__ method, all attributes will be set before the second instance is created, and you will no longer need to resize, since all subsequent dictionaries will have the correct size.
Thus, the dictionary keys will remain shared, no matter what additions are made , before a second instance can be created . Doing this in __init__ is the most logical way to achieve this.
This means that it does not mean that attributes set later are not shared; they can still be shared between examples; until you compile any of the dictionaries. Therefore, after creating the second instance, the keys cease to be shared if one of the following events occurs:
- a new attribute resizes the dictionary
- the new attribute is not a string attribute (dictionaries are highly optimized for the general case with all-keys-are-strings keys).
- the attribute is inserted in a different order; for example
a.foo = None and b.bar = None , here b.bar has an incompatible insertion order, since the shared dictionary has foo . - attribute is deleted. This kills sharing even for one instance . Do not delete attributes if you like generic dictionaries.
So, at the moment when you have two instances (and two dictionaries for exchanging keys), the keys will not be re-shared, but until you run any of the above cases, your instances will continue to share the keys.
It also means that delegating installation attributes to a helper method called from __init__ will not affect the scenario described above, these attributes are still set before creating a second instance. In the end, __init__ will not be able to return before the second method returns.
In other words, you should not worry too much about where you set your attributes. Setting them in the __init__ method makes it easier for you to combine scripts, but any attribute set before creating the second instance is guaranteed to be part of the shared keys.
How to check this: look at the memory size using sys.getsizeof() function ; if creating a copy of the __dict__ matching __dict__ in a larger object, the __dict__ table was split:
import sys def shared(instance): return sys.getsizeof(vars(instance)) < sys.getsizeof(dict(vars(instance)))
Quick demo:
>>> class Foo: ... pass ... >>> a, b = Foo(), Foo()
Only when the threshold is reached (for an empty dictionary with 8 spare slots, resizing occurs when the 6th key is added), the dictionaries lost their general property.
Dictionaries change when they are 2/3, and the size as a whole doubles the size of the table. Thus, the next size will take place when adding the 11th key, then at 22, then 43, etc. So, for a large copy of the dictionary you have much more respite.