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

时间:2011-12-31 18:57:02

标签: python function methods double-underscore

这似乎发生了很多,并且想知道这是Python语言中的要求,还是仅仅是常规问题?

此外,有人可以命名并解释哪些功能倾向于使用下划线,以及为什么(例如__init__)?

7 个答案:

答案 0 :(得分:465)

来自Python PEP 8 -- Style Guide for Python Code

  

Descriptive: Naming Styles

     

使用前导或尾部下划线的以下特殊形式是   认可(这些通常可以与任何案例惯例相结合):

     
      
  • _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本身保留的:“永远不要创建这样的名称;只能按照文档使用它们。”

答案 1 :(得分:50)

其他受访者将双重前导和尾随下划线描述为“特殊”或“魔术”方法的命名约定是正确的。

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

答案 2 :(得分:15)

双下划线包围的名称对Python来说是“特殊的”。它们列在Python Language Reference, section 3, "Data model"

答案 3 :(得分:5)

实际上,当我需要在父类和子类名之间有所不同时,我会使用_方法名。我已经阅读了一些使用这种创建父子类的代码。作为示例,我可以提供此代码:

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

...

答案 4 :(得分:1)

添加了一个示例,以了解__在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

答案 5 :(得分:0)

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

例如, file 表示Python文件的位置,当执行a == b表达式时,将执行 eq

用户当然可以制作自定义的特殊方法,这种情况很少见,但通常可能会修改某些内置的特殊方法。 (例如,您应该使用 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

答案 6 :(得分:0)

后方双下划线(名称修饰)/来自Python文档

  

任何形式的__spam标识符(至少两个下划线,   在文字上最多替换一个结尾的下划线)   _classname__spam,其中classname是当前的类名,其中前导下划线被去除。这种处理是无视的   到标识符的句法位置,因此可以用来   定义类私有实例和类变量,方法,变量   存储在全局变量中,甚至变量存储在实例中。私人   该类在其他类的实例上。

     

名称修饰旨在使类易于定义   “私有”实例变量和方法,无需担心   关于由派生类定义的实例变量,或与   实例变量通过类外的代码实现。请注意,   设计规则主要是为了避免发生事故;仍然有可能   坚定的灵魂去访问或修改被认为是   私人的。