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

Chu*_*sta 393 python methods function double-underscore

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

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

Mic*_*urr 495

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本身保留的:"永远不要发明这样的名称;只能按照文档使用它们".

  • 雷蒙德还解释了为什么你想在这段视频中大约34分钟开始出现名称损坏行为:https://www.youtube.com/watch?v = HTLu2DFOdTg (5认同)
  • 因此,在名称中单个前导下划线和双前导下划线之间的选择有点像在C++和Java中选择protected和private?_single_leading_underscore可以由子项更改,但__double_leading_underscore不能? (5认同)
  • `__double_leading_underscore` * 仍然是公开的*,变量被简单地重命名以避免冲突。 (2认同)

Ray*_*ger 55

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

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


Ign*_*ams 18

双下划线包围的名称对Python来说是"特殊的".它们列在Python语言参考,第3节"数据模型"中.

  • 最后,从 Google 快速找到 Python 参考手册的右侧部分。谢谢。 (3认同)

Hit*_*ahu 12

添加了一个示例来了解 __ 在 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
Run Code Online (Sandbox Code Playgroud)

  • 是否有地方记录了前导“__”作为“强私有”的使用?我在链接的文档中没有看到它,也没有在该文档中的 [`__` 标识符](https://docs.python.org/3/reference/lexical_analysis.html#reserved-classes-of-身份标识)。那里记录了单个前导下划线;使用名称修饰的类私有名称的双前导下划线记录在此处;但似乎称“__”为“超级私有”是一种误导,可能会导致人们在文件级函数上使用它,而据我所知,它实际上没有任何意义。 (2认同)

小智 6

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

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))
Run Code Online (Sandbox Code Playgroud)

...

和有_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)
    )
Run Code Online (Sandbox Code Playgroud)

...


Sha*_*thi 5

此约定用于特殊变量或方法(所谓的 \xe2\x80\x9cmagic method\xe2\x80\x9d),例如__init____len__。这些方法提供特殊的语法特征或做特殊的事情。

\n\n

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

\n\n

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

\n\n
class A:\n    def __init__(self, a):  # use special method \'__init__\' for initializing\n        self.a = a\n    def __custom__(self):  # custom special method. you might almost do not use it\n        pass\n
Run Code Online (Sandbox Code Playgroud)\n