Python: что означает двойное подчеркивание — name mangling, магические методы и приватные атрибуты

0
11

Содержание

Краткая памятка по двойному подчеркиванию в Python

  1. Используйте _var для обозначения защищенных атрибутов (соглашение).
  2. Используйте __var для приватных атрибутов с name mangling.
  3. Не создавайте свои __var__ — это зарезервировано для магических методов.
  4. Применяйте _ для игнорирования ненужных значений в распаковке.
  5. Используйте var_ для избежания конфликта с ключевыми словами.
  6. Помните, что name mangling работает только внутри класса.
  7. Не полагайтесь на __var для строгой приватности — это все еще доступно.
  8. Используйте одиночное подчеркивание _ для разделения разрядов в числах.
  9. В интерпретаторе _ хранит последний результат вычисления.
  10. Избегайте двойного подчеркивания в начале для публичных API.
  11. При наследовании __var родителя не переопределяется в потомке.
  12. Для временных переменных используйте _.
  13. Магические методы (__init__, __str__) не переопределяйте без необходимости.
  14. Следуйте PEP 8 для именования с подчеркиваниями.

Символ нижнего подчеркивания

Зачем нужны методы с двумя нижними подчёркиваниями в - изображение номер один
Зачем нужны методы с двумя нижними подчёркиваниями в — изображение номер один

Этот пост посвящен объяснению того, как использовать нижнее подчеркивание (_) и как его понимать в различных контекстах.

Случай использования в интерпретаторе

ubuntu - изображение номер два
ubuntu — изображение номер два

Интерпретатор Python’а хранит последнее значение в специальной переменной с именем «_». Эта особенность используется в первую очередь в стандартном интерпретаторе CPython, как, впрочем, и в других интерпретаторах Python.

Случай игнорирования значений

Регулярные выражения в - изображение номер три
Регулярные выражения в — изображение номер три

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

Случай придания специфических значений именам переменных и функций

Особенности - изображение номер четыре
Особенности — изображение номер четыре

Нижнее подчеркивание часто используется в наименованиях. Стиль кодирования PEP8 в языке Python вводит соглашения по использованию следующих случаев наименований.

Случай использования функций Internationalization(i18n) или «Localization(l10n)

Строки, регулярные выражения, локализация и интернационализация - изображение номер пять
Строки, регулярные выражения, локализация и интернационализация — изображение номер пять

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

Случай разделения чисел в числе или символов в литерале

Первые шаги - изображение номер шесть
Первые шаги — изображение номер шесть

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

Подчеркивание в именах¶

Всё о подчеркиваниях в - изображение номер семь
Всё о подчеркиваниях в — изображение номер семь

В Python подчеркивание в начале или в конце имени указывает на специальные имена. Чаще всего это всего лишь договоренность, но иногда это действительно влияет на поведение объекта.

Подчеркивание как имя¶

Использование подчеркивания в коде на - изображение номер восемь
Использование подчеркивания в коде на — изображение номер восемь

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

Например, если из строки line надо получить MAC-адрес, IP-адрес, VLAN и интерфейс и отбросить остальные поля, можно использовать такой вариант:

Такая запись говорит о том, что нам не нужны третий и четвертый элементы.

Но тогда может быть непонятно, почему переменные lease и entry_type не используются дальше. Если понятней использовать имена, то лучше назвать переменные именами вроде ignored.

Аналогичный прием может использоваться, когда переменная цикла не нужна:

Подчеркивание в интерпретаторе¶

Зачем - изображение номер девять
Зачем — изображение номер девять

В интерпретаторе python и ipython подчеркивание используется для получения результата последнего выражения

Одно подчеркивание перед именем¶

What is the - изображение номер десять
What is the — изображение номер десять

Одно подчеркивание перед именем указывает, что имя используется как внутреннее.

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

ЧИТАТЬ ТАКЖЕ:  Полное руководство: как удалить Python с компьютера на Windows 10

Но, кроме того, при импорте вида from module import * не будут импортироваться объекты, которые начинаются с подчеркивания.

Если импортировать все объекты из модуля, то те, которые начинаются с подчеркивания, не будут импортированы:

Одно подчеркивание после имени¶

Одно подчеркивание после имени используется в том случае, когда имя объекта или параметра пересекается со встроенными именами.

Два подчеркивания перед именем¶

Подчеркивание в - изображение номер двенадцать
Подчеркивание в — изображение номер двенадцать

Два подчеркивания перед именем метода используются не просто как договоренность. Такие имена трансформируются в формат «имя класса + имя метода». Это позволяет создавать уникальные методы и атрибуты классов.

Если создать подкласс, то метод __configure не перепишет метод родительского класса Switch:

Два подчеркивания перед и после имени¶

Язык программирования - изображение номер тринадцать
Язык программирования — изображение номер тринадцать

Переменная __name__ чаще всего используется, чтобы указать, что определенная часть кода должна выполняться, только когда модуль выполняется напрямую:

А переменная __file__ может быть полезна в определении текущего пути к файлу скрипта:

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

Двойное подчеркивание в Python

python - i - изображение номер четырнадцать
python — i — изображение номер четырнадцать

И подчеркивание (_), и двойное подчеркивание (__) имеют большое значение в мире программирования Python и чрезмерно используются программистами для различных целей. Двойные подчеркивания очень удобны и часто встречаются в коде Python.

Используйте двойное подчеркивание в Python

HOW - изображение номер пятнадцать
HOW — изображение номер пятнадцать

Когда двойное подчеркивание приводит к заданному идентификатору (__var), процесс изменения имени происходит на этом конкретном идентификаторе.

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

Вы можете использовать следующий код для объяснения двойного подчеркивания в начале Python.

Объяснение

Основы программирования на языке - изображение номер шестнадцать
Основы программирования на языке — изображение номер шестнадцать

Этот процесс изменения имен переменных с двойным подчеркиванием в начале полностью прозрачен для программиста. Изменение имени взаимодействует и изменяет все, что начинается с двойного подчеркивания, включая функции.

Использование двойного начального и конечного подчеркивания в Python

10 изящных способов использования подчеркивания в - изображение номер семнадцать
10 изящных способов использования подчеркивания в — изображение номер семнадцать

Когда переменная окружена двойным подчеркиванием как с ведущей, так и с конечной сторон, процесс изменения имени к ней не применяется.

Змеиный регистр

Что такое звездочки * в - изображение номер восемнадцать
Что такое звездочки * в — изображение номер восемнадцать

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

Магические имена

Python - изображение номер девятнадцать
Python — изображение номер девятнадцать

Опять же, думаю, все видели, что имена магических методов и магических переменных начинаются и заканчиваются в двух знаком подчеркивания (__init__). Вот, например, так:

Конфликт с ключевым словом

Программирование на - изображение номер двадцать
Программирование на — изображение номер двадцать

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

Бывает актуально, если вы пишите какой-то биндинг к сторонней библиотеке, где, к несчастью, некоторые понятия имеют такое же имя как и ключевые слова:

Но! Если вы пишите классовый метод, принято первый аргумент называть cls, а не class_.

Приватные члены

Learn - изображение номер двадцать один
Learn — изображение номер двадцать один

Приватные члены – это такие, которые предполагаются только для внутреннего использования классом или модулем. Они не должны использоваться из-вне, хотя Python и не запрещает это делать. Есть способы получить доступ к любым приватным вещам, если очень нужно.

Разделение на приватные и публичные члены – это механизм сокрытия (пожалуйста, не путайте с инкапсуляцией). Я писал про разницу между ними в статье «Сокрытие в Python». Здесь кратко напомню.

Еще приватнее или name mangling

What are single and double underscores before an object name? - изображение номер двадцать два
What are single and double underscores before an object name? — изображение номер двадцать два

Кстати, на слэнге двойное подчеркивание называется dunder. Добавление третьего и четвертого подчеркиваний к дополнительным эффектам не приведет!

Игнорирование

Если вам не нужно значение переменной, назовите его просто подчеркиванием.

Так же при распаковке коллекций в переменные вы можете применить сколько угодно подчеркиваний.

Разделение разрядов в числах

Процедуры и функции - изображение номер двадцать четыре
Процедуры и функции — изображение номер двадцать четыре

Фишка добавлена в Python 3.6. Можно разделять разряды в длинных числах для облегчения чтения кода.

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

How to comment and uncomment out multiple highlighted lines in python - изображение номер двадцать пять
How to comment and uncomment out multiple highlighted lines in python — изображение номер двадцать пять

⚠️ Лично я не знал, про эту фишку, пока не стал писать эту статью. А между тем, она супер удобна, если вы используете интерпретатор Python как калькулятор:

ЧИТАТЬ ТАКЖЕ:  Что нужно знать и уметь Python Junior: навыки и требования

Именование с подчеркиванием в Python

Файлы - изображение номер двадцать шесть
Файлы — изображение номер двадцать шесть

В Python подчеркивание _ имеет особое значение. Хотя подчеркивание используется просто для переменных и функций snake-case во многих языках, в Python он имеет особое значение. Они широко используются в различных сценариях, включая случаи, когда мы хотим игнорировать некоторое значение, или при объявлении переменных, методов и т.д.

Одиночное и двойное подчеркивание имеет значение в именах переменных и методов Python. Некоторые из этих значений просто условны, а некоторые навязываются интерпретатором Python.

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

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

Одиночный лидирующий символ подчеркивания: _var

Урок 3 - изображение номер двадцать семь
Урок 3 — изображение номер двадцать семь

Префикс подчеркивания предназначен для подсказки другому программисту, что переменная или метод, начинающийся с одного подчеркивания, предназначен для внутреннего использования. Это соглашение определено в PEP 8.

Имя с префиксом подчеркивания (например, _spam) должно рассматриваться как непубличная часть API (будь то функция, метод или член данных). Его следует рассматривать как деталь реализации, которая может быть изменена без предварительного уведомления.

Давайте инстанцируем вышеуказанный класс и попробуем получить доступ к name и _age атрибутам.

Двойное ведущее подчеркивание: __var

Python - 010 - изображение номер двадцать восемь
Python — 010 — изображение номер двадцать восемь

Использование двойного подчеркивания (__) перед именем (в частности, перед именем метода) не является условностью; оно имеет конкретное значение для интерпретатора.

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

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

Чтобы лучше понять, мы создадим наш игрушечный класс для экспериментов:

Давайте посмотрим на атрибуты его объекта, используя встроенную dir() функцию:

Из приведенного выше списка атрибутов объекта видно, что и self._age остаются неизменными и ведут себя так же.

Предполагаемое поведение здесь почти эквивалентно финальным переменным в Java и невиртуальным в C++.

Одиночный нижний колонтитул: var_

Комментарии в - изображение номер двадцать девять
Комментарии в — изображение номер двадцать девять

Для избежания конфликтов с ключевыми словами Python используется соглашение об именовании с одним подчеркиванием в конце

Двойное ведущее и направляющее подчеркивание: __var__

Двойная линия (двойное подчеркивание) в - изображение номер тридцать
Двойная линия (двойное подчеркивание) в — изображение номер тридцать

Имена, имеющие ведущее и последующее двойное подчеркивание (“dunders”), зарезервированы для специального использования, например, для метода __init__ для конструкторов объектов, или __call__ для того, чтобы сделать объект вызываемым. Эти методы известны как dunder методы.

Честно говоря, ничто не мешает нам написать собственное dunder (глупость) имя, но лучше не использовать их в наших программах, чтобы избежать столкновений с будущими изменениями в языке Python. (ссылка на статью которая подробно описывает dunders исчерпывающе).

Одиночное подчеркивание: _

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

Например, в следующем цикле нам не нужен доступ к бегущему индексу, и мы можем использовать “ _ ”, чтобы указать, что это всего лишь временное значение:

Часто задаваемые вопросы о двойном подчеркивании в Python

Вопрос: Что означает двойное подчеркивание перед именем переменной?
Ответ: Это механизм name mangling, который делает атрибут приватным, изменяя его имя на _ИмяКласса__атрибут.

Вопрос: Чем отличается __var от _var?
Ответ: _var — это соглашение о том, что атрибут защищенный, а __var запускает name mangling для предотвращения случайного переопределения.

Вопрос: Для чего используется __init__?
Ответ: Это магический метод (dunder method), который вызывается при создании объекта для его инициализации.

Вопрос: Что такое name mangling?
Ответ: Это процесс, при котором Python автоматически переименовывает атрибуты с двойным подчеркиванием в начале, добавляя имя класса.

Вопрос: Можно ли использовать двойное подчеркивание для обычных переменных?
Ответ: Да, но это не рекомендуется, так как это может привести к неожиданному поведению из-за name mangling.

Вопрос: Что означает двойное подчеркивание до и после имени?
Ответ: Это зарезервировано для магических методов Python, таких как __str__, __len__ и других.

Вопрос: Как двойное подчеркивание влияет на наследование?
Ответ: Атрибуты с __var в родительском классе не переопределяются в дочернем, так как их имена изменяются с учетом класса.

Вопрос: Что такое _ в Python?
Ответ: Одиночное подчеркивание используется как временная переменная, для игнорирования значений или хранения последнего результата в интерпретаторе.

Вопрос: Как двойное подчеркивание используется в числах?
Ответ: В Python 3.6+ двойное подчеркивание (на самом деле одиночное) используется для разделения разрядов, например 1_000_000.

Вопрос: Почему __var__ не подвергается name mangling?
Ответ: Потому что двойное подчеркивание с обеих сторон зарезервировано для специальных методов и не изменяется интерпретатором.