514

This "underscoring" seems to occur a lot, and I was wondering if this was a requirement in the Python language, or merely a matter of convention?

Also, could someone name and explain which functions tend to have the underscores, and why (__init__, for instance)?

ZF007
  • 3,521
  • 8
  • 32
  • 45
Chuck Testa
  • 5,357
  • 3
  • 15
  • 11
  • 9
    @AustinHenley: Not for double underscores before *and after* the name. You're thinking of underscores solely *before* the name. –  Dec 31 '11 at 19:09
  • 2
    Related: ["What is the historical reason why Python uses the double underscore for Class Private members?"](http://programmers.stackexchange.com/questions/228216/what-is-the-historical-reason-why-python-uses-the-double-underscore-for-class-pr). – David Cary Sep 20 '16 at 11:07
  • 4
    Possible duplicate of [What is the meaning of a single- and a double-underscore before an object name?](http://stackoverflow.com/questions/1301346/what-is-the-meaning-of-a-single-and-a-double-underscore-before-an-object-name) – MackM Apr 12 '17 at 16:58
  • @MackM Note that this question asks about underscores *before and after* the name, and the duplicate target that you proposed asks about underscores only *before* the name. Though, I admit that some of the answers there cover this case as well. – Georgy May 28 '20 at 14:07

6 Answers6

679

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

Descriptive: Naming Styles

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.

Note that names with double leading and trailing underscores are essentially reserved for Python itself: "Never invent such names; only use them as documented".

Stevoisiak
  • 20,148
  • 23
  • 110
  • 201
Michael Burr
  • 321,763
  • 49
  • 514
  • 739
  • 9
    Raymond also explains why you'd want the name mangling behavior starting at around 34 minutes into this video: https://www.youtube.com/watch?v=HTLu2DFOdTg – johncip May 26 '14 at 06:42
  • 8
    So the choice between the single leading underscore and double leading underscore in a name is a bit like choosing between protected and private in C++ and Java? _single_leading_underscore can be changed by children, but __double_leading_underscore can't? – Alex W Jun 04 '14 at 21:00
  • 2
    `__double_leading_underscore` is *still public*, the variable is simply renamed to avoid a clash. – c z Sep 21 '17 at 10:06
  • The new mangled method name, having a single leading underscore, is private. E.g. `__boo` becomes `_FooBar__boo` – hi2meuk Aug 07 '21 at 15:22
72

The other respondents are correct in describing the double leading and trailing underscores as a naming convention for "special" or "magic" methods.

While you can call these methods directly ([10, 20].__len__() for example), the presence of the underscores is a hint that these methods are intended to be invoked indirectly (len([10, 20]) for example). Most python operators have an associated "magic" method (for example, a[x] is the usual way of invoking a.__getitem__(x)).

Raymond Hettinger
  • 199,887
  • 59
  • 344
  • 454
27

Names surrounded by double underscores are "special" to Python. They're listed in the Python Language Reference, section 3, "Data model".

Anton Tarasenko
  • 7,375
  • 10
  • 54
  • 85
Ignacio Vazquez-Abrams
  • 740,318
  • 145
  • 1,296
  • 1,325
  • Finally, a fast pointer from Google to the right part of the Python reference manual. Thank you. – MrBrody Aug 10 '21 at 22:56
6

Actually I use _ method names when I need to differ between parent and child class names. I've read some codes that used this way of creating parent-child classes. As an example I can provide this code:

class ThreadableMixin:
   def start_worker(self):
       threading.Thread(target=self.worker).start()

   def worker(self):
      try:
        self._worker()
    except tornado.web.HTTPError, e:
        self.set_status(e.status_code)
    except:
        logging.error("_worker problem", exc_info=True)
        self.set_status(500)
    tornado.ioloop.IOLoop.instance().add_callback(self.async_callback(self.results))

...

and the child that have a _worker method

class Handler(tornado.web.RequestHandler, ThreadableMixin):
   def _worker(self):
      self.res = self.render_string("template.html",
        title = _("Title"),
        data = self.application.db.query("select ... where object_id=%s", self.object_id)
    )

...

5

Added an example to understand the use of __ in python. Here is the list of All __

https://docs.python.org/3/genindex-all.html#_

Certain classes of identifiers (besides keywords) have special meanings. Any use of * names, in any other context, that does not follow explicitly documented use, is subject to breakage without warning

Access restriction using __

"""
Identifiers:
-  Contain only (A-z, 0-9, and _ )
-  Start with a lowercase letter or _.
-  Single leading _ :  private
-  Double leading __ :  strong private
-  Start & End  __ : Language defined Special Name of Object/ Method
-  Class names start with an uppercase letter.
-

"""


class BankAccount(object):
    def __init__(self, name, money, password):
        self.name = name            # Public
        self._money = money         # Private : Package Level
        self.__password = password  # Super Private

    def earn_money(self, amount):
        self._money += amount
        print("Salary Received: ", amount, " Updated Balance is: ", self._money)

    def withdraw_money(self, amount):
        self._money -= amount
        print("Money Withdraw: ", amount, " Updated Balance is: ", self._money)

    def show_balance(self):
        print(" Current Balance is: ", self._money)


account = BankAccount("Hitesh", 1000, "PWD")  # Object Initalization

# Method Call
account.earn_money(100)

# Show Balance
print(account.show_balance())

print("PUBLIC ACCESS:", account.name)  # Public Access

# account._money is accessible because it is only hidden by convention
print("PROTECTED ACCESS:", account._money)  # Protected Access

# account.__password will throw error but account._BankAccount__password will not
# because __password is super private
print("PRIVATE ACCESS:", account._BankAccount__password)

# Method Call
account.withdraw_money(200)

# Show Balance
print(account.show_balance())

# account._money is accessible because it is only hidden by convention
print(account._money)  # Protected Access
Hitesh Sahu
  • 38,157
  • 14
  • 182
  • 142
  • Is there a place that documents the use of leading `__` as `strong private`? I don't see it in the linked document, nor under the link in that document to [`__` identifiers](https://docs.python.org/3/reference/lexical_analysis.html#reserved-classes-of-identifiers). Single leading underscore is documented there; double leading underscore for class private names using name mangling is documented there; but it seems calling `__` "super private" is misleading, and may lead to people using it on file-level functions, where as far as I know it actually has no meaning. – hlongmore May 20 '22 at 20:19
2

This convention is used for special variables or methods (so-called “magic method”) such as __init__ and __len__. These methods provides special syntactic features or do special things.

For example, __file__ indicates the location of Python file, __eq__ is executed when a == b expression is executed.

A user of course can make a custom special method, which is a very rare case, but often might modify some of the built-in special methods (e.g. you should initialize the class with __init__ that will be executed at first when an instance of a class is created).

class A:
    def __init__(self, a):  # use special method '__init__' for initializing
        self.a = a
    def __custom__(self):  # custom special method. you might almost do not use it
        pass
wovano
  • 3,264
  • 4
  • 18
  • 43
Shagun Pruthi
  • 1,643
  • 13
  • 18