这似乎发生了很多,并且想知道这是Python语言中的要求,还是仅仅是常规问题?
此外,有人可以命名并解释哪些功能倾向于使用下划线,以及为什么(例如__init__
)?
答案 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是当前的类名,其中前导下划线被去除。这种处理是无视的 到标识符的句法位置,因此可以用来 定义类私有实例和类变量,方法,变量 存储在全局变量中,甚至变量存储在实例中。私人 该类在其他类的实例上。
名称修饰旨在使类易于定义 “私有”实例变量和方法,无需担心 关于由派生类定义的实例变量,或与 实例变量通过类外的代码实现。请注意, 设计规则主要是为了避免发生事故;仍然有可能 坚定的灵魂去访问或修改被认为是 私人的。