As you probably know, Python doesn't enforce protected/private attributes: all class attributes are globally accessible. However, there is a convention that attributes whose names start with at least one _ are an implementation detail and not part of the public API.
Double-underscored names are a slight hack used for the following use case. Suppose you have
class Mapping:
def __init__(self, iterable):
self.update(iterable)
def update(self, iterable):
<stuff>
class MappingSubclass(Mapping):
def update(self, keys, values):
<stuff>
Notice that Mapping defines a method update, which is called in __init__. The subclass then redefines update with a different signature. Since the initialiser of the subclass is inherited from Mapping while the update method is overridden, this will cause an error when run.
To avoid this, you want Mapping's copy of update to be specific to that class, and not changed by subclasses. To do this, Python lets you 'magically' include the name of the class in the attribute, which is done by prefixing it with a double underscore. That is, if we used __update instead of update, Python would automatically rename the attribute to (something like) _Mapping__update. Then, when a subclass overwrote update, the double-underscore version would remain class-local and hence not break. So we would do
class Mapping:
def __init__(self, iterable):
self.__update(iterable)
def update(self, iterable):
<stuff>
__update = update # private copy for initialiser
class MappingSubclass(Mapping):
def update(self, keys, values):
<stuff>
Now, even though update is overwritten in MappingSubClass, the private copy of update saved as __update is mangled to _Mapping__update and hence the code works as it should.
Unfortunately, this does have the problem that attribute names prefixed with double-attributes look like one thing but are actually another. The usual advice, then, is not to use them unless you find yourself in this type of situation; a single underscore will suffice elsewhere.
__-prefixed method names get name-mangled, and thus are not accessible from outside the object?__-prefixed attributes are accessible outside, but their names are mangled, such that, for example, an attribute defined as__my_attributeinMyClasswould be accessible as_MyClass__attribute_name. There is a naming convention of using a single underscore to prefix an attribute that shouldn't be accessed outside the class.