Underscores in Python Naming Styles


Ever wondered why there are many methods in Python starting with two underscores that __look_like_this? What’s the difference between a single, and a double underscore before a method name?

The other day when I was doing my Python assignment, working on my project Tic-Tac-Toe Online in Python, I tried to build a GUI on top of the command-line based client. I thought it would be a better OOP design to create a GUI class that extends the command-line based Client class, and keep the code for the client unchanged. However, I encountered some problems that really puzzled me. – I was unable to override some of the methods in the base class.

Let’s take a look at the following code.

class Base:
    def test(self):
        print("Calling __foo()");

    def __foo(self):
        print("Why is the base class being called?");

class Sub(Base):
    def __foo(self):
        print("I'm trying to call this!");
        print("This should override the __foo()!!");

a = Sub();

I was trying to override the methods defined in the super class. The variable a is supposedly an instance of Sub, and the test() should therefore call the __foo() on the Sub class. However, the output of the program was mind-boggling:

Calling __foo()
Why is the base class being called?

The first line is easy. Yeah the test() method from Base class was being class. However, when the next line self.__foo() was being executed, why did it call the one in class Base instead of Sub? Isn’t this an instance of Sub?

This really just didn’t make sense to me. How is it possible that Python doesn’t have method overriding? Obviously Python is an OOP language, but how does inheritance in Python work if I can’t even define a method in a subclass that overrides that in its superclass?

After some quick research, I realized the problem here has to do with the naming conventions in Python. For a scripting language that doesn’t have any access modifier (such as public and private), underscores in method names are actually taken to set the accessibility of the method to facilitate the encapsulation of components.

From the Python PEP 8 – Style Guide for Python Code:

The following special forms using leading or trailing underscores are recognized (these can generally be combined with any case convention):

  • _single_leading_underscore : weak “internal use” indicator. E.g. from M import * does not import objects whose name starts with an underscore.
  • single_trailing_underscore_ : used by convention to avoid conflicts with Python keyword, e.g. Tkinter.Toplevel(master, class_='ClassName')
  • __double_leading_underscore : when naming a class attribute, invokes name mangling (inside class FooBar, __boo becomes _FooBar__boo ; see below).
  • __double_leading_and_trailing_underscore__ : “magic” objects or attributes that live in user-controlled namespaces. E.g. __init__ , __import__ or __file__ . Never invent such names; only use them as documented.

Now, everything finally started making sense to me! the double leading underscore __ actually invokes name mangling so in this example __foo() would become _Base__foo() and _Sub__foo() respectively on each class. Thus, here _Sub__foo() doesn’t override _Base__foo().

Because Python doesn’t really have private methods, the double-underscore are thus reserved as some sort of access modifier so we can use the double-underscore __ to avoid methods being accidentally overridden by its subclasses and thus to prevent accidental access.

In comparison, the single-underscore _ doesn’t really control the accessibility of the methods. As the official PEP states, it is just a weak “internal use” indicator. It prevents the methods being imported with from M import *, but that’s all it does.

However, the __double_leading_and_trailing_underscore__ should be avoided at all times, because they are reserved for Python built-in methods.

Chen Yumin
Chen Yumin

Hi, my name is Chen Yumin.
I am the author of the stuff you're reading right now.

Latest Project

Connect With Me

Enjoy what you see? Follow me on:


Subscribe via RSS