Почему Python так любит подчеркивание

Несколько уловок с подчеркиванием улучшат ваш код Python

Многие языки программирования используют символ подчеркивания «_» во многих сценариях, как и Python. Если вы когда-либо использовали Python для объектно-ориентированного программирования, вы должны знать, что функция-конструктор объекта Python - __init__(). Это, вероятно, наиболее распространенный сценарий, при котором нам нужно использовать символы подчеркивания в Python.

Однако есть гораздо больше случаев, когда мы можем использовать одно или несколько подчеркиваний для некоторых трюков. Это могло бы улучшить наш код с точки зрения надежности или даже добавить некоторые новые функции. В этой статье я перечислю несколько приемов подчеркивания. Надеюсь, они могут помочь.

1. Временная переменная

Первый трюк, который я хочу представить, связан с временной переменной. Когда мы не знаем имя переменной или не хотим называть переменную, нам может помочь подчеркивание.

Последний результат REPL

REPL относится к «Прочитать и оценить цикл печати». Когда мы запускаем что-то в консоли Python, результат будет буферизирован в REPL как переменная. У этой переменной нет имени, но мы можем получить его с помощью символа подчеркивания.

Наиболее типичный пример - Jupyter Notebook. Предположим, мы запускаем что-то в ячейке, тогда мы можем получить результат, используя подчеркивание в следующей ячейке.

Однако следует подчеркнуть, что значение «Нет» не буферизуется. Следовательно, значение подчеркивания НЕ будет заменено, как в примере ниже.

Анонимная переменная

Как правило, мы также можем использовать знак подчеркивания для имени переменной, когда нам на самом деле не нужно ее называть. Обычно это просто потому, что нам не нужно впоследствии использовать переменную, но ее нужно где-то разместить.

for _ in range(10000):
    # Do something 10000 times
    pass

В приведенном выше примере нам просто нужен цикл for для запуска фрагмента кода 10 тысяч раз. Однако цикл не важен. Итак, мы можем использовать подчеркивание в качестве индекса цикла for.

Также стоит упомянуть, что большинство IDE знает это «практическое правило», так что подчеркивание не будет проверяться при его использовании впоследствии. Вместо этого, если мы используем именованную переменную в этом цикле for, некоторые инструменты IDE могут предупредить, что мы «определили переменную, не используя ее».

Заполнитель

Еще одно распространенное использование подчеркивания в качестве временной переменной - использовать его в качестве заполнителя. Это обычно используется, когда мы хотим извлечь значение (я) из кортежа. См. Пример ниже.

my_tuple = (1, 2)
x, _ = my_tuple
print(x)

Как показано, мы получаем первое значение из кортежа и присваиваем его переменной x. Второй игнорируется, потому что мы используем подчеркивание в качестве «заполнителя».

Еще одна хитрость, о которой вы, возможно, не знаете, заключается в том, что мы можем использовать звездочку с подчеркиванием в качестве «заполнителя» для нескольких значений. Предположим, у нас есть кортеж с несколькими значениями, и мы хотим получить из него первое и последнее значения.

my_long_tuple = (1, 2, 3, 4, 5)
x, *_, z = my_long_tuple
print('x =', x)
print('z =', z)

Независимо от того, сколько значений находится в середине, x, *_, z всегда будет получать первое и последнее значения.

2. Улучшает читаемость.

Этот, наверное, известен многим разработчикам, но я все же хочу разместить его здесь. Этот небольшой трюк в значительной степени улучшает читаемость чисел в программе.

num = 1_000_000
print(num)

Обычно мы используем запятую для разделения каждых трех цифр в номере, чтобы мы могли легко прочитать номер. В Python мы не можем использовать запятые, но можем использовать подчеркивание, которое делает то же самое.

Кроме того, не волнуйтесь, для некоторых культурных и обычаев, где не группируются каждые 3 цифры, мы можем буквально поставить подчеркивание где угодно. На результат это тоже не повлияет.

num = 100_0000
print(num)

3. Разрешение конфликтов имен

Подчеркивание также часто используется, чтобы избежать конфликтов в пространстве имен. Обратите внимание, что на уровне переводчика нет определения этого. Итак, это еще одно «практическое правило» использования подчеркивания.

Например, мы хотим определить функцию для получения «класса» некоторых продуктов. Если мы напишем код следующим образом, это вызовет ошибку.

def print_class(class):
    print('Class:', class)

Это потому, что термин class является одним из зарезервированных ключевых слов в Python. В частности, Python думает, что мы определяем класс объектов, но синтаксис явно неправильный.

В этом случае практическое правило заключается в следующем: после переменной ставится нижнее подчеркивание.

def print_class(class_):
    print('Class:', class_)
print_class('Premium')

Конечно, нам не обязательно использовать «класс» в качестве имени переменной, потому что это всего лишь имя переменной. Однако иногда это улучшает читаемость нашего кода, НЕ избегая зарезервированных ключевых слов.

4. Частные / защищенные атрибуты и функции

Подчеркивание также может использоваться для защиты некоторых атрибутов и функций, на которые мы не хотим, чтобы нижестоящий поток ссылался, или просто не нужно позволять им импортировать или вызывать.

Защитить импорт

Например, в файле .py мы можем определить ряд констант и функций. Затем этот файл Python должен быть импортирован другими в качестве библиотеки. Однако в этом файле могут быть некоторые локальные вспомогательные функции, которые не следует импортировать.

В этом случае мы можем поставить подчеркивание перед константами или функциями, чтобы они не импортировались from ... import *.

Давайте создадим файл lib.py и поместим в него следующие две функции.

def test_func():
    print("I'm a test")
def _test_func():
    print("I'm a _test")

Затем давайте импортируем все из этого файла.

from lib import *

После этого мы можем убедиться, что импортирован test_func(), но не _test_func().

Однако обратите внимание, что это довольно «удобный» инструмент, который не позволяет нам импортировать ненужные функции. Это НЕ мешает пользователю явно импортировать его.

Если мы явно импортируем функцию, она будет работать.

from lib import _test_func

5. Защита атрибутов / функций класса

Мы можем не только импортировать, но и использовать символы подчеркивания для защиты атрибутов и функций в классе от внешнего вызова.

Это можно сделать, добавив двойные подчеркивания __ перед атрибутами или функциями, которые необходимо защитить.

Давайте определим класс с именем Person, а затем создадим его экземпляр.

class Person():
    def __init__(self, name, age):
        self.name = name
        self.__age = age
    def show(self):
        print(f"My name is {self.name} and I'm {self.__age} years old.")
    def __show(self):
        print(f"Hey {self.name}, you shouldn't call this function.")
p1 = Person('Chris', 33)

Итак, мы можем вызвать функцию show() для печати заранее определенной строки.

Однако, если мы попытаемся вызвать атрибут __name и функцию __show(), которые «защищены» двойным подчеркиванием, будет выдана ошибка.

Опять же, эта «защита» не ограничивается на уровне переводчика. Это удобно, если мы хотим скрыть что-то в классе от вызова. Но есть способ явно вызвать. Просто добавьте перед ними _<class_name>.

6. Магические функции

Что ж, все знают магические функции, но они очень важны, поэтому я не хочу их пропускать. Функция __init__(), которая использовалась в предыдущем примере, является своего рода волшебной функцией. Кроме того, одной из наиболее важных будет функция __repr__() в классе. Он определяет, что выводить при печати объекта. Если вы знакомы с Java, это почти эквивалент метода toString().

Давайте определим класс без функции __repr__() и попробуем распечатать объект.

class Person():
    def __init__(self, name, age):
        self.name = name
        self.age = age
p1 = Person('Chris', 33)
print(p1)

Он просто сообщает нам имя класса и адрес памяти, что не очень помогает. Теперь давайте определим функцию __repr__() и попробуем еще раз.

def __repr__(self):
        return f"My name is {self.name} and I'm {self.age} years old."

Резюме

В этой статье я представил несколько приемов, связанных с подчеркиванием в языке программирования Python. Иногда это позволяет нам иметь определенные возможности, иногда улучшает читаемость и надежность. Кроме того, он предоставляет некоторые удобства для защиты импорта и атрибутов / функций классов.

Эти приемы стоит знать, и иногда они важны для понимания кода от других. Надеюсь, эти советы помогут.

Жизнь коротка, используйте Python!