Зачем нужны и в названиях объектов

от admin

Зачем нужны и в названиях объектов

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

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

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

Не будем затягивать и, пожалуй, начнем.

Переменные

Один из самых раздражающих видов переменных — это такие переменные, что дают ложное представление о природе данных, которые они хранят. Эдакие переменные-мошенники.

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

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

Когда вы делаете запрос ( requests.Request ), то получаете ответ ( requests.Response ), так отразите это у себя в коде:

Не r , не res , не resp и уж точно не req , а именно response . res , r , resp (про req и вовсе молчу) — это все переменные, содержание которых можно понять, только взглянув на их объявление, а зачем прыгать к объявлению, когда можно изначально дать подходящее название?

Давайте рассмотрим еще один пример, но теперь из Django:

Когда вы видите где-то в коде users_list , то вы совершенно справедливо ожидаете, что сможете сделать так:

Но нет, вы этого сделать не можете, так как .filter() возвращает QuerySet , а QuerySet далеко не list :

Если вам очень важно указывать суффикс, то укажите хотя бы такой, который соответствует действительности:

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

Привязка названия переменной к типу хранящихся в ней данных — это чаще всего плохая идея, особенно когда вы работаете с динамическими языками. В случаях, когда очень нужно отметить, что объект представляет собой контейнерный тип данных, достаточно просто указать название переменной во множественном числе:

или, если вам уж совсем неймется и вы в любом случае намерены использовать суффиксы, то лучше добавить суффикс _seq (меньшее из зол), чтобы отметить, что это последовательность:

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

Еще одним видом раздражающих переменных являются переменные с сокращенными именами.

Вернемся к requests и рассмотрим этот код:

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

Конкретно в случае requests скрипя зубами можно простить подобное сокращение, когда код занимает не более 5-10 строк и записывается вот так:

Тут контекстный менеджер позволяет дополнительно выделить объемлющий блок для переменной s .

Но гораздо лучше написать как есть, а именно:

Вы можете возразить, что это ведь более многословный вариант, но я вам отвечу, что это окупается, когда вы читаете код и сразу понимаете, что session — это Session . Поймете ли вы это по переменной s , не взглянув на ее определение?

Рассмотрим еще один пример:

Вы видите dict и можете захотеть сделать так:

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

Таким образом, когда вы указываете в названии переменной тип хранящихся в ней данных, вы по сути выступаете гарантом того, что в этой переменной в любой момент времени выполнения программы должен содержаться указанный тип данных. Зачем нам брать на себя такую ответственность, если это прямая обязанность интерпретатора или компилятора? Лучше потратить время на придумывание хорошего названия переменной, чем на попытки понять, почему переменные ведут себя не так, как вы ожидаете.

В приведенном выше примере выбор переменной достаточно неудачный, и можно было бы дать имя, точнее выражающее контекст (не нужно бояться использовать имена, относящиеся к предметной области), однако даже в этом случае можно было бы сделать этот код лучше:

или даже так, что более идиоматично:

Комментарии-кэпы

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

Возьмем небольшой пример из JavaScript:

Первое, что мелькает в голове, когда видишь такое — это «Спасибо, кэп!». Зачем описывать то, что и так понятно без комментария? Зачем дублировать информацию, которую нам уже рассказывает код? Этим и отличается хороший комментарий от плохого — хороший комментарий заставляет вас испытать благодарность тому, кто его написал, а плохой — лишь раздражение.

Давайте попробуем сделать этот комментарий полезным:

А еще лучше прибегнуть к более декларативному подходу и избавиться от комментария вообще:

Говоря о комментариях, нельзя не упомянуть мертвый код. Мертвый код, пожалуй, раздражает куда больше, чем бесполезные комментарии, так как вы еще и должны разбираться, был ли код закомментирован временно (для отладки каких-то частей системы) или все же разработчик просто забыл его удалить?

Как бы там ни было, мертвому коду не место в модулях и он должен быть удален! Если вдруг окажется, что это было что-то важное, то вы сможете просто откатиться к нужной версии (если, конечно, вы не программист-амиш, что не пользуется системой контроля версий).

Методы

Умное именование функций и методов — это то, что приходит только с опытом проектирования API, и потому достаточно часто можно встретить случаи, когда методы ведут себя не так, как мы ожидаем.

Рассмотрим пример с методом:

В коде мы выразили весьма однозначный вопрос: «Имеются ли у этого человека публикации?», но какой ответ мы получили?

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

А для получения постов вы можете использовать более подходящее название:

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

Список литературы для изучения вопроса

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

Класс и объект в Python

Python — это процедурно-ориентированный и одновременно объектно-ориентированный язык программирования.

Процедурно-ориентированный

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

Объектно-ориентированный

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

Создание класса в Python

Синтаксис для написания нового класса:

  • Для создания класса пишется ключевое слово class , его имя и двоеточие (:). Первая строчка в теле класса описывает его. (По желанию) получить доступ к этой строке можно с помощью ClassName.__doc__
  • В теле класса допускается объявление атрибутов, методов и конструктора.
Атрибут:

Атрибут — это элемент класса. Например, у прямоугольника таких 2: ширина ( width ) и высота ( height ).

Метод:
  • Метод класса напоминает классическую функцию, но на самом деле — это функция класса. Для использования ее необходимо вызывать через объект.
  • Первый параметр метода всегда self (ключевое слово, которое ссылается на сам класс).
Конструктор:
  • Конструктор — уникальный метод класса, который называется __init__ .
  • Первый параметр конструктора во всех случаях self (ключевое слово, которое ссылается на сам класс).
  • Конструктор нужен для создания объекта.
  • Конструктор передает значения аргументов свойствам создаваемого объекта.
  • В одном классе всегда только один конструктор.
  • Если класс определяется не конструктором, Python предположит, что он наследует конструктор родительского класса.

Создание объекта с помощью класса Rectangle:

Создание объекта с помощью класса Rectangle

Расчет площади класса Rectangle

Что происходит при создании объекта с помощью класса?

При создании объекта класса Rectangle запускается конструктор выбранного класса, и атрибутам нового объекта передаются значения аргументов. Как на этом изображении:

Конструктор выбранного класса

Конструктор с аргументами по умолчанию

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

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

Конструктор с аргументами по умолчанию

Сравнение объектов

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

Если объект AA — это просто ссылка на объект BB , то он не будет сущностью, занимающей отдельную ячейку памяти. Вместо этого он лишь ссылается на местоположение BB .

Как происходит сравнение объектов

Оператор == нужен, чтобы узнать, ссылаются ли два объекта на одно и то же место в памяти. Он вернет True , если это так. Оператор != вернет True , если сравнить 2 объекта, которые ссылаются на разные места в памяти.

Сравнение объектов

Атрибуты

В Python есть два похожих понятия, которые на самом деле отличаются:

  1. Атрибуты
  2. Переменные класса

Стоит разобрать на практике:

Атрибут

Объекты, созданные одним и тем же классом, будут занимать разные места в памяти, а их атрибуты с «одинаковыми именами» — ссылаться на разные адреса. Например:

Объекты одного класса занимают разные места в памяти

Изменение значений атрибутов

Python умеет создавать новые атрибуты для уже существующих объектов. Например, объект player1 и новый атрибут address .

Встроенные атрибуты класса

Объекты класса — дочерние элементы по отношению к атрибутам самого языка Python. Таким образом они заимствуют некоторые атрибуты:

Атрибут Описание
__dict__ Предоставляет данные о классе коротко и доступно, в виде словаря
__doc__ Возвращает строку с описанием класса, или None , если значение не определено
__class__ Возвращает объект, содержащий информацию о классе с массой полезных атрибутов, включая атрибут __name__
__module__ Возвращает имя «модуля» класса или __main__ , если класс определен в выполняемом модуле.

Переменные класса

Переменные класса в Python — это то же самое, что Field в других языках, таких как Java или С#. Получить к ним доступ можно только с помощью имени класса или объекта.

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

Переменные класса

У каждой переменной класса есть свой адрес в памяти. И он доступен всем объектам класса.

Составляющие класса или объекта

В Python присутствует функция dir , которая выводит список всех методов, атрибутов и переменных класса или объекта.

Как придумать крутое название или гайд по неймингу

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

Что такое нейминг?

Нейминг (от англ. «name», имя) — процесс разработки названия для компании, под которым бренд или товар регистрируется и выводятся на рынок. Важные требования к названию — оригинальность и простота, чтобы потенциальный покупатель легко запомнил продукт.

Начинающие предприниматели часто думают, что создание имени бренда — простое дело, главное, чтобы продукт был хорошим. Но это не так, увы. В качестве доказательств мы собрали несколько примеров неудачного нейминга со всего мира.

  • Например, в России совершенно не сложилось с детским питанием «Bledina», а крем «Dermo-Expertise» очень плохо продавался, потому что рождал у русскоязычного человека нехорошие ассоциации.
  • На Украине перестали рекламировать бренд «Wispa», потому что с украинского «вiспа» переводится как «оспа».
  • Во всех странах Латинской Америки продажи «Chevrolet Nova» не пошли вверх, потому что по-испански «no va» означает «не едет».
  • «Otsuka Bld» — это крупный японский производитель лекарственных препаратов, некоторые из которых даже экспортируются в Россию, но под другим названием (интересно почему…;) ).
  • Магазин подержанных товаров для детей «Kids Еxchange» стал предметом насмешек, в первую очередь, из-за логотипа, в котором длинное название бренда было написано в одно слово «Kidsexchange». Тут и возникло недопонимание: то ли это «Kids exchange», то ли «Kid sex change» (дословно «смена пола ребенка»).

Иногда можно сделать это своей фишкой (например, название канала Юрия Дудя «ВДудь» или мороженное «Отмороженное»), но есть шанс не выстрелить и вынуждено проводить ребрендинг.

Согласно статистике, которой поделилась компания Feedvisor, 74% потребителей считают название бренда важным фактором при выборе продукта, а 59% назвали название очень важным фактором.

Правила нейминга

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

  • Лаконичность и звучность. Название должно не только чётко произноситься, но и легко записываться, желательно даже на транскрипте. Хороший пример — ООО «Импульс».
  • Стилистика. Имя отражает стиль, суть продукта или услуги, а также сферу деятельности. Например, бренд детских вещей «Карапуз» или «ДочкиСыночки».
  • Уникальность. Разработанное имя не должно быть ранее зарегистрировано и использовано какой-либо другой фирмой.
  • Отсутствие подтекстов, особенно негативных. Хорошо, конечно, когда имя вашей компании имеет множество трактовок, но лучше с подобным быть поаккуратнее. Примеры — салон-красоты «Царица» или банк «Развитие».
  • Соответствие месту и концепции (если это возможно). Например, можно назвать бар «У моста», если он действительно располагается рядом с мостом в городе, а сеть барбершопов — «BORODA».
  • Рекомендуется также применять различные методы психолингвистики, словообразования и позиционирования. При выборе имени особое внимание обращается на лексическое значение, эмоциональную и стилистическую окраску, этимологию и морфологию, а также эстетику слов. Пример: сеть парикмахерских или «Chop-Chop» (с англ. «Быстро!», «Шевелись!»). В таком имени явно заложена скорость работы сотрудников, а ещё в слогах «чоп-чоп» можно услышать звук стригущих ножниц.

В таком подходе главное не переусердствовать. Ведь главная задача нейминга — чтобы получившееся имя было понятным для широкой аудитории.

Методы нейминга

Как же разработать крутое название и подружить бренд с аудиторией? Если вы не знаете с чего начать, то можно использовать:

Ассоциации

Учитываются все варианты, связанные с какими-либо свойствами бренда. Например, клининговая компания «Чистый дом». Из названия понятно, чем занимается компания, и что является результатом её деятельности.

Аббревиатуры

Тут название бренда складывается из сокращений. Сюда же относят акронимы, когда нейм составляется из первых букв полного названия. Например, BMW — акроним, расшифровывающийся как Bayerische Motoren Werke. Российский примеры — банк ВТБ — Внешний Торговый Банк. Или издательство МИФ: Манн, Иванов и Фербер.

Неологизмы

Фантазийные слова, которые сложно подделать, но легко запатентовать: Google, ВкусВилл или Гурмания (выдуманные топонимы).

Усечения

За основу берётся несколько ключевых слов, связанных с преимуществами или свойствами, затем их «распиливают», а получившиеся части компонуют в нейм. Например, «Живо» — галерея живописи, или «Fanta» — сокращение от «fantastic».

Имена

Тут все просто — берётся имя, фамилия или отчество. Способ широко распространён, но в то же время не всегда демонстрирует качества продукта. Из примеров: Adidas (Adi Dassler — тут и метод усечения, кстати), Calvin Klein, Лаборатория Касперского, Тинькофф Банк ну или магазины «Машенька», «Ирина», «Мария» которые есть почти в каждом городе.

Рифмы

Яркий пример в этой категории — «7-Eleven» (Seven-Eleven). Кроме того, название отображает режим работы магазинов — с семи до одиннадцати.

Превосходство

В данном случае используются приставки супер-, гипер-, мега- и другие. Пример — компания «Мега-Ойл», которая демонстрирует основной продукт и масштабность деятельности. Также можно показать превосходство продукта не очень актуальным, но имеющим право на жизнь, методом — использовать гиперболы: «Мир инструмента», «Вселенная текстиля», «Империя стали».

Доменный-нейминг

Суть этого способа — использовать домен в качестве наименования. Например, «АВТО.РУ» или «MAIL.RU». Доменные имена уже давно стали мощным маркетинговым инструментом, потому что благодаря им пользователи запоминают и узнают бренды, названия компаний и сервисов.

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

Из всего написанного делаем вывод, что хороший нейминг:

  1. Закрепляется в памяти потребителя.
  2. Успешно конкурирует с другими названиями, потому что их трудно перепутать.
  3. Связывается в умах с товаром или услугой компании.
  4. Соответствует вкусу потребителя, вызывает только положительные ассоциации.
  5. Имеет потенциал и подходит для расширения товарных категорий, выхода на международный рынок и так далее.
  6. Хорошо звучит и широко используется в обычной жизни (это особенно актуально для сектора B2C).

Генераторы названий

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

    . На сайте можно ввести основные ключевые слова, связанные со сферой деятельности фирмы, затем выбрать категорию и нажать на кнопку, чтобы сервис сгенерировал нейм. . Принцип действия аналогичный: выбираете категорию, добавляете ключевое слово и жмёте на кнопку для старта генерации. названий. Позволяет на старте выбрать не только категорию бизнеса, но и количество слов в новом бренде. . Вводим стартовое слово, количество букв в будущем названии и алгоритм словообразования. С количеством букв лучше не перебарщивать. Если выставить значение, например, «17», генератор выдаёт весьма странные варианты. названий фирм, товаров, имён персонажей. Работает аналогично предыдущему, но не даёт возможности задать стартовое ключевое слово. . У этого сервиса возможности куда шире. Например, можно задать количество букв для будущего нейма и даже выбрать подходящий алгоритм. После нажатия на кнопку «Сгенерировать» будет выдана уйма вариантов, нужно будет просто выбрать из них что-то стоящее.

А если хотите зарегистрировать новый домен для бизнеса или найти свободный, то обратите внимание на два наших бесплатных сервиса:

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

И расскажите в комментариях приходилось ли вам давать названия новым продуктам или событиям? Делитесь опытом в комментариях, возможно, кому-то сейчас поможет именно ваш совет.

Нижнее подчеркивание в Python

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

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

Нижнее подчеркивание ( _ ) — это уникальный символ.

Если вы программист Python, вам, вероятно, встречались подобные строки:

  • for _ in range(100)
  • __init__(self)
  • _ = 2

Значение символа подчеркивания зависит от контекста.

Можно найти пять различных вариантов использования символа нижнего подчеркивания:

  1. Использование в интерпретаторе
  2. Игнорирование значений
  3. Использование в цикле
  4. Разделение цифр в числах
  5. Именование
    • Одинарное подчеркивание в начале
    • Одинарное подчеркивание в конце
    • Двойное подчеркивание в начале
    • Двойное подчеркивание в начале и в конце

Что ж, давайте разберем все эти варианты на примерах.

1. Использование в интерпретаторе

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

Вы можете использовать нижнее подчеркивание как обычную переменную. К примеру, давайте рассмотрим следующий код:

2. Игнорирование значений

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

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

Проигнорировать можно не только одно значение, но и несколько. Делается это с помощью комбинации звездочки и нижнего подчеркивания *_ .

Например, давайте рассмотрим следующий пример:

3. Использование в цикле

Также вы можете использовать нижнее подчеркивание ( _ ) в качестве переменной в цикле. Рассмотрим следующий код, чтобы лучше понять, как это работает:

4. Разделение цифр в числах

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

К примеру, миллион можно представить как 1_000_000 .

Вы также можете использовать символ нижнего подчеркивания ( _ ) для разделения частей двоичных, восьмеричных или шестнадцатеричных чисел.

Например, это может выглядеть так:

binary = 0b_0010, octa = 0o_64, hexa = 0x_23_ab

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

5. Именование с использованием подчеркивания (_)

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

  • Единичное подчеркивание в начале: _variable
  • Единичное подчеркивание в конце: variable_
  • Двойное подчеркивание в начале: __variable
  • Двойное подчеркивание начале и в конце: __variable__
5.1. Единичное подчеркивание в начале

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

Рассмотрим следующий пример:

Заметим, что одинарное подчеркивание в начале имени не мешает нам получить доступ к переменной.

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

Давайте напишем следующий код в файле my_funtions :

Если вы импортируете все методы и имена из my_functions.py , Python не импортирует имена, начинающиеся с единичного подчеркивания в начале. Мы получим следующий результат:

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

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

5.2. Одинарное подчеркивание в конце

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

Давайте посмотрим, как это может выглядеть:

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

5.3. Двойное подчеркивание в начале

Двойное нижнее подчеркивание в начале используется для искажения имени.

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

Искажение имени означает, что интерпретатор Python изменяет имя переменной таким образом, что при наследовании классов не происходит конфликтов.

Давайте посмотрим на следующий пример:

Приведенный выше код возвращает все атрибуты объекта класса. Посмотрим на наши переменные в списке атрибутов.

Переменная self.a появляется в списке без каких-либо изменений.

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

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

Давайте создадим еще один класс, который наследуется от класса Sample , чтобы увидеть, как работает переопределение:

Здесь снова работает искажение имени. Программа изменяет obj2.__c на _SecondClass__c . Например, попробуем напечатать этот элемент, используя измененный атрибут:

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

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

Вы также можете использовать двойные подчеркивания для имен методов. Рассмотрим пример:

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

Обратимся к следующему примеру:

Вы поняли концепцию? Если нет, попробуйте перечитать ещё раз.

5.4. Двойное подчеркивание в начале и в конце

В Python вы найдете разные имена, которые начинаются и заканчиваются двойным подчеркиванием. Они называются магическими методами или дандер-методами (англ. dunder — сокращение от Double Under (Underscores) — букв. “двойное подчеркивание”).

Использование данных методов в качестве имен переменных приведет к конфликтам. Поэтому с ними нужно быть аккуратнее.

Заключение

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

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

Зачем Python столько знаков подчеркивания?

Знак подчеркивания “_” — не изобретение Python, другие языки программирования также используют символ “_” в своих сценариях; однако в семантике языка Python знак подчеркивания фигурирует особенно часто: первое, с чем сталкивается новичок в изучении объектно-ориентированного программирования на Python — это метод конструктора объекта __init__ , у которого в сигнатуре аж четыре подчеркивания!

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

В статье перечислены следующие приёмы разностороннего улучшения кода с помощью символа нижнего подчеркивания “_”:

  1. Создание временных переменных на Python.
  2. Улучшение читаемости кода на Python.
  3. Разрешение конфликта имён в программе на Python.
  4. Создание изолированных (внутренних, инкапсулированных, “приватных”) атрибутов для объектов Python.
  5. Создание защищенных от перезаписи атрибутов для объектов Python.
  6. Переопределение магических методов и специальных атрибутов объектов Python.

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

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

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

Аббревиатура REPL расшифровывается как “Read Evaluate Print Loop”, что в переводе означает “Чтение Оценка Печать Цикл”. Запуская что-либо в консоли Python, результат работы программы будет записан в REPL в виде переменной. У этой переменной нет имени, и в качестве идентификатора для неё как раз подойдет один знак нижнего подчеркивания.

Ознакомиться с крайне типичным примером получения сохраненных в REPL результатов выполнения программы можно при использовании среды Jupyter Notebook. Предположим, в первой ячейке вашего блокнота инициирован запуск чего-либо — это значит, что в последующей ячейке доступ к результату выполнения программного кода первой ячейки можно получить с помощью символа нижнего подчеркивания:

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

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

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

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

Более того, большинство из популярных интегрированных средств разработки по умолчанию знакомы с “эмпирическим правилом” идентификатора-подчеркивания, поэтому переменная с таким идентификатором не проверяется на предмет использования в остальном коде программы; и наоборот, при назначении переменной в вышеописанном цикле for уникального идентификатора, некоторые инструменты интегрированной среды разработки могут начать выдавать разработчику предупреждение о том, что он случайно “определил переменную без её использования”.

Универсальный заполнитель

Еще одно распространенное использование символа нижнего подчеркивания в качестве идентификатора временной переменной — это создание заполнителя; зачастую такой приём используется для извлечения значений из кортежа, как в примере ниже.

Как показано на примере, в качестве значения переменной x присваивается значение первого из элементов кортежа. А вот вторая переменная игнорируется, поскольку идентификатор-подчёркивание без лишних слов даёт понять, что она используется в качестве “заполнителя”.

Также следует упомянуть о малоизвестном трюке, который заключается в совместном использовании символа звездочки с идентификатором-подчеркиванием ради создания переменной-“заполнителя” с несколькими значениями. Предположим, что обозначен кортеж с несколькими элементами, задача — получить из него значения первого и последнего элементов:

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

2. Улучшение читаемости кода

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

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

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

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

Символ нижнего подчеркивания также используется многими разработчиками для избегания появления конфликтов в пространствах имён, при том что на уровне интерпретатора для такого использования подчеркивания нет никакого официального функционала. Таким образом, это еще одно “эмпирическое правило” использования символа нижнего подчеркивания в коде.

Например, необходимо определить функцию получения “класса” (разновидности) некоторых продуктов. Если написать код следующим образом, то будет выброшено исключение SyntaxError :

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

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

Конечно, никто не обязан использовать именно слово “class” в качестве идентификатора для переменной, потому что это просто имя переменной; однако иногда именно такое название существенно улучшает читаемость кода, в таком случае не хочется — и не нужно, как мы узнали только что — избегать использования зарезервированных ключевых слов.

4. Изолированный атрибут объекта

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

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

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

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

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

Далее, в другом файле, выполним импорт всего содержимого из нашего модуля lib.py :

Теперь легко проверить, что первая test_func() была успешно импортирована, чего нельзя сказать о функции _test_func() !

Однако, пожалуйста, воспринимайте вышеописанный приём как “удобное средство”, предотвращающее импорт ненужных функций. Данный трюк НЕ помешает другому программисту явно импортировать куда угодно всё, что он захочет.

Явный импорт продолжает работать:

5. Защищенные атрибуты класса

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

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

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

Таким образом, для вывода на экран заранее заданной строки идеально подойдёт метод show() :

Тем не менее, если попытаться получить доступ к значению атрибута __name или вызвать метод __show(), которые “защищены” двойными подчеркиваниями в самом начале их идентификаторов, то произойдёт выброс исключения, и программа прекратит работу.

Опять же, эта “защита” не прописана на уровне интерпретатора, она удобна лишь тогда, когда хочется скрыть от вызова какой-то внутренний функционал класса, потому что всегда можно прибегнуть к явному вызову атрибута или метода: просто добавьте перед ними указание _<имя_класса> :

6. Специальные атрибуты и магические методы

Про магические методы знает каждый, но данный аспект настолько важен, что его нельзя пропускать так или иначе. Метод-конструктор __init__() , который использовался в одном из первых примеров статьи, как раз таки относится к магическим методам, в документации языка программирования Python называемым “специальные атрибуты”. Кроме метода-конструктора, одним из самых важных магических методов каждого класса можно назвать __repr__() , определяющий, что должно быть выведено при запросе строкового представления объекта. Если вы знакомы с Java, то легко узнаете в методе __repr__() примерный аналог toString() .

Для примера определим класс Person и переопределим его метод __repr__() , чтобы настроить вывод на экран при передаче функции print() экземпляра данного класса.

В первом примере метод __repr__() не переопределён, в следствии чего функция print() просто сообщает нам имя класса и его адрес в памяти компьютера, что не очень полезно для отладки:

Теперь давайте переопределим функцию __repr__() и попробуем снова:

Вывод

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

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

Пара слов об именовании переменных и методов

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

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

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

Не будем затягивать и, пожалуй, начнем.

Переменные

Один из самых раздражающих видов переменных — это такие переменные, что дают ложное представление о природе данных, которые они хранят. Эдакие переменные-мошенники.

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

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

Когда вы делаете запрос ( requests.Request ), то получаете ответ ( requests.Response ), так отразите это у себя в коде:

Не r , не res , не resp и уж точно не req , а именно response . res , r , resp (про req и вовсе молчу) — это все переменные, содержание которых можно понять, только взглянув на их объявление, а зачем прыгать к объявлению, когда можно изначально дать подходящее название?

Давайте рассмотрим еще один пример, но теперь из Django:

Когда вы видите где-то в коде users_list , то вы совершенно справедливо ожидаете, что сможете сделать так:

Но нет, вы этого сделать не можете, так как .filter() возвращает QuerySet , а QuerySet далеко не list :

Если вам очень важно указывать суффикс, то укажите хотя бы такой, который соответствует действительности:

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

Привязка названия переменной к типу хранящихся в ней данных — это чаще всего плохая идея, особенно когда вы работаете с динамическими языками. В случаях, когда очень нужно отметить, что объект представляет собой контейнерный тип данных, достаточно просто указать название переменной во множественном числе:

или, если вам уж совсем неймется и вы в любом случае намерены использовать суффиксы, то лучше добавить суффикс _seq (меньшее из зол), чтобы отметить, что это последовательность:

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

Еще одним видом раздражающих переменных являются переменные с сокращенными именами.

Вернемся к requests и рассмотрим этот код:

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

Конкретно в случае requests скрипя зубами можно простить подобное сокращение, когда код занимает не более 5-10 строк и записывается вот так:

Тут контекстный менеджер позволяет дополнительно выделить объемлющий блок для переменной s .

Но гораздо лучше написать как есть, а именно:

Вы можете возразить, что это ведь более многословный вариант, но я вам отвечу, что это окупается, когда вы читаете код и сразу понимаете, что session — это Session . Поймете ли вы это по переменной s , не взглянув на ее определение?

Рассмотрим еще один пример:

Вы видите dict и можете захотеть сделать так:

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

Таким образом, когда вы указываете в названии переменной тип хранящихся в ней данных, вы по сути выступаете гарантом того, что в этой переменной в любой момент времени выполнения программы должен содержаться указанный тип данных. Зачем нам брать на себя такую ответственность, если это прямая обязанность интерпретатора или компилятора? Лучше потратить время на придумывание хорошего названия переменной, чем на попытки понять, почему переменные ведут себя не так, как вы ожидаете.

В приведенном выше примере выбор переменной достаточно неудачный, и можно было бы дать имя, точнее выражающее контекст (не нужно бояться использовать имена, относящиеся к предметной области), однако даже в этом случае можно было бы сделать этот код лучше:

или даже так, что более идиоматично:

Комментарии-кэпы

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

Возьмем небольшой пример из JavaScript:

Первое, что мелькает в голове, когда видишь такое — это «Спасибо, кэп!». Зачем описывать то, что и так понятно без комментария? Зачем дублировать информацию, которую нам уже рассказывает код? Этим и отличается хороший комментарий от плохого — хороший комментарий заставляет вас испытать благодарность тому, кто его написал, а плохой — лишь раздражение.

Давайте попробуем сделать этот комментарий полезным:

А еще лучше прибегнуть к более декларативному подходу и избавиться от комментария вообще:

Говоря о комментариях, нельзя не упомянуть мертвый код. Мертвый код, пожалуй, раздражает куда больше, чем бесполезные комментарии, так как вы еще и должны разбираться, был ли код закомментирован временно (для отладки каких-то частей системы) или все же разработчик просто забыл его удалить?

Как бы там ни было, мертвому коду не место в модулях и он должен быть удален! Если вдруг окажется, что это было что-то важное, то вы сможете просто откатиться к нужной версии (если, конечно, вы не программист-амиш, что не пользуется системой контроля версий).

Методы

Умное именование функций и методов — это то, что приходит только с опытом проектирования API, и потому достаточно часто можно встретить случаи, когда методы ведут себя не так, как мы ожидаем.

Рассмотрим пример с методом:

В коде мы выразили весьма однозначный вопрос: «Имеются ли у этого человека публикации?», но какой ответ мы получили?

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

А для получения постов вы можете использовать более подходящее название:

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

Список литературы для изучения вопроса

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

Зачем нужны && и & после метода в классе? C++

Наткнулся на код, где в конце методов были && и &. Нечто подобное:

Что делают символы & и && ПОСЛЕ метода? (Зачем они нужны в параметрах я знаю). Где можно почитать о таком их использовании и как это называется?

Это перегрузка по вызову функций для lvalue (&) и rvalue (&&). Называется reference-qualified member functions.

То есть, если написать

будет вызвано clone с одним &, потому что q это lvalue.

То будет вызван второй вариант.

Зачем это нужно? очевидно, что в некоторых случаях второй вариант может приводить к утечками и хотелось бы избежать и это можно сделать

Читать:
Альт плюс ф4 что это

Похожие статьи