标签归档:double-underscore

为什么某些函数在函数名称前后都有下划线“ __”?

问题:为什么某些函数在函数名称前后都有下划线“ __”?

这种“强调”似乎经常发生,我想知道这是否是Python语言中的要求,还是仅仅是出于约定?

另外,有人可以说出并解释哪些函数倾向于带有下划线,以及为什么(__init__例如)?

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


回答 0

Python PEP 8-Python代码样式指南

描述性:命名样式

可以识别以下使用前划线或后划线的特殊形式(通常可以将它们与任何大小写惯例结合使用):

  • _single_leading_underscore:“内部使用”指示器较弱。例如from M import *,不导入名称以下划线开头的对象。

  • single_trailing_underscore_:按惯例用于避免与Python关键字发生冲突,例如

    Tkinter.Toplevel(master, class_='ClassName')

  • __double_leading_underscore:在命名类属性时,调用名称修饰(在类FooBar内部,__boo变为_FooBar__boo;见下文)。

  • __double_leading_and_trailing_underscore__:位于用户控制的命名空间中的“魔术”对象或属性。例如__init____import____file__。请勿发明此类名称;仅按记录使用它们。

请注意,带有双引号和尾部下划线的名称本质上是为Python本身保留的:“切勿发明此类名称;仅将其用作文档”。

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


回答 1

其他受访者在将双下划线和下划线作为“特殊”或“魔术”方法的命名惯例进行描述时是正确的。

尽管您可以直接调用这些方法([10, 20].__len__()例如),但是下划线的存在暗示这些方法旨在间接调用(len([10, 20])例如)。大多数python运算符都有一个关联的“魔术”方法(例如,这a[x]是调用的常用方法a.__getitem__(x))。

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


回答 2

带有双下划线的名称是Python的“特殊”名称。它们在Python语言参考的第3节“数据模型”中列出。

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


回答 3

实际上,当需要在父类和子类名称之间进行区分时,我使用_方法名称。我已经阅读了一些使用这种方法创建父子类的代码。例如,我可以提供以下代码:

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

和具有_worker方法的孩子

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

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


回答 4

此约定用于诸如__init__和的特殊变量或方法(所谓的“魔术方法”)__len__。这些方法提供特殊的语法功能或执行特殊的操作。

例如,__file__表示__eq__执行a == b表达式时执行的Python文件的位置。

用户当然可以制作一个自定义的特殊方法,这种情况很少见,但是通常可能会修改一些内置的特殊方法(例如,您应该使用该类来初始化类,该类__init__将在类的实例首先执行时初始化)被建造)。

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

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

回答 5

添加了一个示例来了解__在python中的用法。这是所有__的列表

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

某些类别的标识符(除关键字外)具有特殊含义。在任何其他情况下,*名称的任何使用,如果未遵循明确记录的使用,均会在没有警告的情况下发生破损。

使用__的访问限制

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

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