Це "підкреслення", здається, трапляється багато, і мені було цікаво, чи це вимога мови Python, чи просто питання конвенції?
Також хтось може назвати та пояснити, які функції, як правило, мають підкреслення, і чому ( __init__
наприклад)?
Це "підкреслення", здається, трапляється багато, і мені було цікаво, чи це вимога мови Python, чи просто питання конвенції?
Також хтось може назвати та пояснити, які функції, як правило, мають підкреслення, і чому ( __init__
наприклад)?
Відповіді:
З Python PEP 8 - Посібник зі стилю для Python Code :
Описово: Назви стилі
Розпізнаються наступні спеціальні форми, що використовують провідні або кінцеві підкреслення (вони, як правило, можуть поєднуватися з будь-якою умовою)
_single_leading_underscore
: слабкий показник "внутрішнього використання". Напр.from M import *
, Не імпортуються об'єкти, ім'я яких починається з підкреслення.
single_trailing_underscore_
: використовується умовно, щоб уникнути конфліктів із ключовим словом Python, наприклад
Tkinter.Toplevel(master, class_='ClassName')
__double_leading_underscore
: при іменуванні атрибуту класу викликає mangling імені (всередині класу FooBar,__boo
стає_FooBar__boo
; див. нижче).
__double_leading_and_trailing_underscore__
: "магічні" об'єкти або атрибути, які живуть у керованих користувачем просторах імен. Наприклад__init__
,__import__
чи__file__
. Ніколи не вигадуйте таких імен; використовувати їх лише задокументовано.
Зауважте, що імена з подвійними провідними та кінцевими підкресленнями по суті зарезервовані для самого Python: "Ніколи не вигадуйте таких імен; використовуйте їх лише як задокументовано".
__double_leading_underscore
все ще є загальнодоступною , змінна просто перейменована, щоб уникнути зіткнення.
Інші респонденти правильно описують подвійні провідні та зворотні підкреслення як умову іменування "спеціальних" чи "магічних" методів.
Хоча ви можете викликати ці методи безпосередньо ( [10, 20].__len__()
наприклад), наявність підкреслень - це натяк на те, що ці методи мають бути покликані побічно ( len([10, 20])
наприклад). Більшість операторів пітона мають пов'язаний з ними "магічний" метод (наприклад, a[x]
звичайний спосіб виклику a.__getitem__(x)
).
Імена, оточені подвійними підкресленнями, є "особливими" для Python. Вони перераховані в довідці про мову Python, розділ 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)
)
...
Ця умова використовується для спеціальних змінних чи методів (так званого "магічного методу"), таких як __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
Додано приклад для розуміння використання __ у 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