ChatGPT解决这个技术问题 Extra ChatGPT

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

这种“下划线”似乎经常出现,我想知道这是否是 Python 语言的要求,或者仅仅是约定的问题?

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

@AustinHenley:不用于名称前后的双下划线。您只在名称之前考虑下划线。
@MackM请注意,此问题询问名称前后的下划线,而您提出的重复目标仅询问名称之前的下划线。不过,我承认那里的一些答案也涵盖了这种情况。

S
Stevoisiak

Python PEP 8 -- Style Guide for Python Code

描述性:命名样式 识别以下使用前导或尾随下划线的特殊形式(这些通常可以与任何大小写约定结合使用): _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 本身保留的:“永远不要发明这样的名称;仅按照文档说明使用它们”。


Raymond 还解释了为什么您希望在此视频的大约 34 分钟开始进行名称修改行为:youtube.com/watch?v=HTLu2DFOdTg
那么名称中单前导下划线和双前导下划线之间的选择有点像在 C++ 和 Java 中选择保护和私有? _single_leading_underscore 可以被孩子改变,但 __double_leading_underscore 不能?
__double_leading_underscore 仍然是公开的,变量被简单地重命名以避免冲突。
具有单个前导下划线的新的重整方法名称是私有的。例如 __boo 变成 _FooBar__boo
R
Raymond Hettinger

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

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


A
Anton Tarasenko

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


最后,来自 Google 的快速指针指向 Python 参考手册的右侧部分。谢谢你。
O
Omadbek Onorov

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

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

...


这不是双下划线前缀的用途吗?
H
Hitesh Sahu

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

是否有记录使用前导 __ 作为 strong private 的地方?我没有在链接的文档中看到它,也没有在该文档中指向 __ identifiers 的链接下看到它。那里记录了单个前导下划线;那里记录了使用名称修饰的类私有名称的双前导下划线;但似乎将 __ 称为“超级私有”具有误导性,并可能导致人们在文件级函数上使用它,据我所知,它实际上没有任何意义。
w
wovano

此约定用于特殊变量或方法(所谓的“魔术方法”),例如 __init____len__。这些方法提供特殊的句法特征或做特殊的事情。

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

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