Python supports semi-private methods through a name mangling trick. The interpreter transforms method names starting with two underscores by prepending it with the class name and some additional underscores, so it becomes impossible to call the method by its original name. Here’s an example:
>>> class T(object): ... def __m(self): pass ... >>> t = T() >>> dir(t) ['_T__m', '__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__'] >>> t.__m() Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'T' object has no attribute '__m'
It is still possible to call the method using its mangled name.
Fortunately, one can still use the original name from within other methods of the same class:
>>> class T(object): ... def __m(self): print "m" ... def public(self): self.__m() ... >>> t = T() >>> t.public() m
It works because bytecode generated for this method uses the mangled name:
>>> import dis >>> dis.dis(t.public) 3 0 LOAD_FAST 0 (self) 3 LOAD_ATTR 0 (_T__m) 6 CALL_FUNCTION 0 9 POP_TOP 10 LOAD_CONST 0 (None) 13 RETURN_VALUE
Post prompted by a colleague’s question.