Python 'hide' methods with __

18,528

While none of this is strictly enforced by python, the naming convention of a double underscore means "private", while a single underscore means "protected".

A double underscore is meant to protect subclasses from causing errors by using the same name. By namespacing them by class name, the defining class can be sure its variables will remain valid.

A single underscore means that subclasses are free to access and modify those same attributes, being shared with the super class.

Both forms suggest that any outside class should not be accessing these.

class A(object):

    __private = 'private'
    _protected = 'protected'

    def show(self):
        print self.__private 
        print self._protected

class B(A):
    __private = 'private 2'
    _protected = 'protected 2'

a = A()
a.show()
#private
#protected

b = B()
b.show()
#private
#protected 2

This example shows that even though class B defined a new __private, it does not affect the inherited show method, which still accesses the original superclass attribute. _protected is however modified and the superclass show method reflects this, because they are the same attribute.

Share:
18,528
Radosław Miernik
Author by

Radosław Miernik

Open source? Embrace, understand, develop.

Updated on June 18, 2022

Comments

  • Radosław Miernik
    Radosław Miernik almost 2 years

    Today I see that - python add _$CLASSNAME$ to methods with name with __.

    Simple example:

    >>> class A:  
    ...     def a(self):  
    ...         self.b()  
    ...     def b(self):  
    ...         print('A.b')  
    ...           
    >>> class B(A):  
    ...     def b(self):  
    ...         print('B.b')  
    ...           
    >>> B().a()  
    B.b
    

    That work, but:

    >>> class A:  
    ...     def a(self):  
    ...         self.__b()  
    ...     def __b(self):  
    ...         print('A.b')  
    ...           
    >>> class B(A):  
    ...     def __b(self):  
    ...         print('B.b')  
    ...           
    >>> B().a()  
    A.b
    

    Why? I don't know, so I dir'ed it. Here it is:

    >>> print([fn for fn in dir(B) if fn[-2:] != '__'])
    ['_A__b', '_B__b', 'a']
    

    Why python do that? Is there way to bypass that?