为什么有些函数有下划线&;__"函数名的前面和后面?

这种“下划线”似乎经常出现,我想知道这是Python语言的要求,还是仅仅是一种惯例?

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

350505 次浏览

Python PEP 8——Python代码的风格指南:

描述性:命名样式 .

以下使用开头或结尾下划线的特殊形式是 已识别(这些通常可以与任何大小写约定结合):

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

  • single_trailing_underscore_:按照约定使用,以避免与Python关键字冲突,例如:

    # EYZ0 < / p >

  • __double_leading_underscore:当命名一个类属性时,调用名称mangling(在类FooBar中,__boo变成_FooBar__boo;见下文)。

  • __double_leading_and_trailing_underscore__:存在于用户控制的命名空间中的“魔术”对象或属性。例如# EYZ1, __import____file__。永远不要编造这样的名字;

  • .

请注意,带有双前导和双尾下划线的名称本质上是为Python本身保留的:“永远不要发明这样的名称;只在文档中使用它们”。

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

其他受访者正确地将双开头和结尾下划线描述为“特殊”或“神奇”方法的命名约定。

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

实际上,当我需要区分父类名和子类名时,我使用_方法名。我读过一些使用这种方式创建父-子类的代码。作为一个例子,我可以提供以下代码:

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

...

这个约定用于特殊的变量或方法(所谓的“魔法方法”),如__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

增加了一个例子来理解__在python中的使用。这里是所有__的列表

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

某些类型的标识符(除了关键字)有特殊的 的意思。在任何其他上下文中使用名称都不会 遵循明确的文件使用,是受破损没有 警告< / p >

使用__的访问限制

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