Роль підкреслення в Python

30 січня 2017 11:55 OlegWock 1893 1

Підкреслення (_) — це не простий символ в Python. В той час, як в більшості мов воно використовується лише для назви функцій та змінних в snake-case, в Python воно має значно ширше застосування. Скоріше за все, ви вже бачили конструкції for _ in range(10) чи __init__(self).

В цьому пості я опишу де, як і навіщо використовується підкреслення. На даний момент є 5 основних кейсів використання підкреслення:

  1. Для зберігання останнього значення в REPL.

  2. Для ігнорування неважливих значень.

  3. Для надання якогось спеціального значення для функції або змінної.

  4. Як аліас для функцій інтернаціоналізації та локалізації.

  5. Для відділення цифр в числах.

А тепер давайте розглянемо кожен пункт детальніше.

При використанні в 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

Джерело перекладу

1893 7

Схожі матеріали:

Коментарі:

Q-Bart

30 Січ 2017 17:47

Якісно. Дякую!

Авторизуйтесь, щоб залишити коментар.