Підкреслення (_
) — це не простий символ в Python. В той час, як в більшості мов воно використовується лише для назви функцій та змінних в snake-case, в Python воно має значно ширше застосування. Скоріше за все, ви вже бачили конструкції for _ in range(10)
чи __init__(self)
.
В цьому пості я опишу де, як і навіщо використовується підкреслення. На даний момент є 5 основних кейсів використання підкреслення:
-
Для зберігання останнього значення в REPL.
-
Для ігнорування неважливих значень.
-
Для надання якогось спеціального значення для функції або змінної.
-
Як аліас для функцій інтернаціоналізації та локалізації.
-
Для відділення цифр в числах.
А тепер давайте розглянемо кожен пункт детальніше.
При використанні в REPL
Інтерпретатор в інтерактивному режимі зберігає останнє вирахуване значення в спеціальній змінній _
. Вперше ця фіча з'явилась в CPython, але зараз підтримується всіма головними інтерпретаторами.
>>> 10
10
>>> _
10
>>> _ * 3
30
>>> _ * 20
600
Ігнорування значень
Підкреслення також використовується для ігнорування значень. Не хочете використовувати якесь значення — присвойте його змінній _
.
# Ігнорування при розпакуванні
x, _, y = (1, 2, 3) # x = 1, y = 3
# Ігнорування декількох значень, лише в Python 3.x
x, *_, y = (1, 2, 3, 4, 5) # x = 1, y = 5
# Ігнорування індексу
for _ in range(10):
do_something()
# Або якогось конкретного значення
for _, val in list_of_tuple:
do_something()
Надання спеціального значення для функції або змінної
Підкреслення найчастіше використовується в назвах. PEP8 описує 4 випадки використання підкреслення в іменах:
_single_leading_underscore
Такий стиль використовується для приватних змінних та функцій в модулі. Всі назви, що починаються з підкреслення будуть проігноровані при from module import *
.
Але Python не може забезпечити справжньої приватності, тому отримати доступ до таких змінних чи функцій дуже легко.
_internal_name = 'one_nodule' # приватна змінна
_internal_version = '1.0' # приватна змінна
class _Base: # приватний клас
_hidden_factor = 2 # приватна змінна
def __init__(self, price):
self._price = price
def _double_price(self): # приватний метод
return self._price * self._hidden_factor
def get_double_price(self):
return self._double_price()
single_trailing_underscore_
Такі імена використовують щоб уникнути конфліктів з ключовими словами в Python. Зазвичай вам не слід їх використовувати.
Tkinter.Toplevel(master, class_='ClassName') # Уникнення конфлікту з ключовим словом 'class'
list_ = List.objects.get(1) # уникнення конфлікту з стандартним типом 'list'
__double_leading_underscore
Це вже більше синтаксис, ніж конвенція про стиль коду. Подвійне підкреслення буде змінювати ім'я атрибуту класу, щоб уникнути колізій з іншими класами. Ця зміна полягає в додаванні _ClassName
до початку назви атрибуту. Тобто якщо ви створите метод __method
в класі, то він буде названий _ClassName__method
.
class A:
def _single_method(self):
pass
def __double_method(self):
pass
class B(A):
def __double_method(self):
pass
Так як ім'я змінюється, тепер ми не можемо отримати доступ до нього за допомогою ClassName.__method
. Дехто використовує цю фічу для створення дійсно приватних атрибутів, але це не правильно і не рекомендується. Детальніше тут.
double_leading_and_trailing_underscore
Так називають спеціальні (магічні) методи. Наприклад, __init__
, __len__
. Деякі з них реалізують синтаксичні фічі, деякі зберігають спеціальні дані: __file__
— вказує на шлях файлу з кодом, __eq__
виконується при виклику виразу a == b
.
Звісно, користувач може створити власні методи
class A:
def __init__(self, a):
self.a = a
def __custom__(self):
pass
Інтернаціоналізація та локалізація
Це лише угода про імена цих функцій, вони ніяк не впливають на синтаксис. Ця традиція прийшла з С, а вбудований модуль gettext
, що використовується для локалізації її використовує, як і Django, найпопулярніший веб-фреймворк.
# офіційні доки : https://docs.python.org/3/library/gettext.html
import gettext
gettext.bindtextdomain('myapplication','/path/to/my/language/directory')
gettext.textdomain('myapplication')
_ = gettext.gettext
# ...
print(_('This is a translatable string.'))
Відділення цифр в числах
Ця фіча досить нова, її додали лише в Python 3.6. Тепер можна використовувати підкреслення для відділення цифр, що покращує вигляд коду.
dec_base = 1_000_000
bin_base = 0b_1111_0000
hex_base = 0x_1234_abcd
print(dec_base) # 1000000
print(bin_base) # 240
print(hex_base) # 305441741
Коментарі (1)