ChatGPT解决这个技术问题 Extra ChatGPT

Why do some functions have underscores "__" before and after the function name?

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)?

@AustinHenley: Not for double underscores before and after the name. You're thinking of underscores solely before the name.
@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.

S
Stevoisiak

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".


Raymond also explains why you'd want the name mangling behavior starting at around 34 minutes into this video: youtube.com/watch?v=HTLu2DFOdTg
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?
__double_leading_underscore is still public, the variable is simply renamed to avoid a clash.
The new mangled method name, having a single leading underscore, is private. E.g. __boo becomes _FooBar__boo
R
Raymond Hettinger

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)).


A
Anton Tarasenko

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


Finally, a fast pointer from Google to the right part of the Python reference manual. Thank you.
O
Omadbek Onorov

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)
    )

...


Isn't this what the double underscore prefix is for?
H
Hitesh Sahu

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

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. 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.
w
wovano

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