问题:为什么某些函数在函数名称前后都有下划线“ __”?
这种“强调”似乎经常发生,我想知道这是否是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:
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
回答 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