I think I understand the concept of \"name mangling\" in python, but there\'s something that I probably missed. Take a look at the following code:
#!/usr/bin/env
As you have noticed, the name used for name mangling is the name of the class where a method is declared, not the derived type of the current object.
The documentation for this feature explicitly gives an example about protecting a variable from a derived class (rather than from external code using an instance variable).
Name mangling is helpful for letting subclasses override methods without breaking intraclass method calls. For example:
class Mapping: def __init__(self, iterable): self.items_list = [] self.__update(iterable) def update(self, iterable): for item in iterable: self.items_list.append(item) __update = update # private copy of original update() method class MappingSubclass(Mapping): def update(self, keys, values): # provides new signature for update() # but does not break __init__() for item in zip(keys, values): self.items_list.append(item)
You are not "missing", to the contrary, you just "found out" what name mangling does: it is made to ensure variables with double underscores inside a method will always see the attribute defined in the same class as that method, and in none of its subclasses.
If you simply want to use the attribute as it is overriden in each subclass, that is the normal behavior for all other attributes, but for the ones prefixed by two underscores.
So, what happens is that the .__data
name used inside func
is itself mangled, at compile time, to _base__data
.
OrderedDict
Python's collections.OrderedDict have an extra trap: Python offers both a pure-python implementation, which uses the __
for its "private attributes", as explained above, but also have a native code implementation in C, and the private structures of that are not exposed to Python.
And the collections
module ends the OrderedDict code block with these lines:
try:
from _collections import OrderedDict
except ImportError:
# Leave the pure Python version in place.
pass
That is: the normal "collections.OrderedDict" is written in C, with a lot of opaque structures, that can't be tapped in by subclasses.
The only way to have access to the Python defined OrderedDict is by
deleting the _collections.OrderedDict
attribute (in the _collections
, not collections
module), and reload the collections
module.
If you do that, and instantiate one ordered dict, the private data structures can be seem:
from imp import reload
import _collections, collections
backup = _collections.OrderedDict
del _collections.OrderedDict
collections = reload(collections)
PyOrderedDict = collections.OrderedDict
_collections.OrderedDict = backup
a = PyOrderedDict()
dir(a)
Out[xx]:
['_OrderedDict__hardroot',
'_OrderedDict__map',
'_OrderedDict__marker',
'_OrderedDict__root',
'_OrderedDict__update',
'__class__',
'__contains__',
'__delattr__',
...
]