Именование — Основы Python
Мы уже умеем работать с переменными в Python. Но недостаточно знать, как ими пользоваться. Еще важно правильно обозначать переменные, чтобы они считывались верно.
Представьте, что мы задали следующую программу:
С подобной программой мы уже работали, но сейчас в ней изменилось имя переменной на x .
Компьютеру без разницы, как мы именуем ту или иную переменную. Названия важны только людям. Обычно программисты гораздо чаще читают чужой код, чем пишут свой. Чтобы коллеги смогли с легкостью прочитать и проанализировать ваш код, нужно понятно называть переменные.
Важно придумать понятное название, которое отражает смысл переменной. При этом важно давать такие имена, которые будут понимать без контекста, без изучения окружающего кода.
Существует общепринятое правило: не используйте транслит для имен — только английский язык. Если вы испытываете сложности с английским, то пользуйтесь переводчиком. Со временем, анализируя чужой код, вы научитесь правильно именовать переменные.
Среди разработчиков есть шутка: «Названия переменных — это одна из самых сложных вещей в программировании». Придумывать названия и правда сложно. Например, сложно назвать переменную, в которой хранится количество неоплаченных заказов от клиентов с задолженностью в предыдущем квартале.
Чтобы проверить себя, попробуйте сделать такое задание:
Придумайте название для переменной, в которой будет храниться «количество братьев и сестер короля».
Запишите его в блокноте или отправьте себе на почту. Не указывайте там ничего, кроме названия переменной. А через несколько уроков мы вернемся к этой теме.
Теперь разберем, как придумывать простые и понятные имена переменных.
Именование переменных
greeting — пример простого имени, но не все имена так просты. Часто они включают в себя несколько слов: например, «имя пользователя». В разных языках применяются разные стили кодирования, и имя переменной будет отличаться.
К именованию переменных есть три основных подхода, которые иногда комбинируют друг с другом. Все эти подходы проявляют себя, когда имя переменной состоит из нескольких слов:
- kebab-case — составные части переменной разделяются дефисом ( my-super-var )
- snake_case — для разделения используется подчеркивание ( my_super_var )
- CamelCase — каждое слово в переменной пишется с заглавной буквы ( MySuperVar )
Переменные в Python именуются в стиле snake_case : слова записываются строчными буквами и разделяются символом подчеркивания _ . Чтобы разобраться подробнее, можете изучить раздел «Как называть переменные» в стандарте PEP8.
Далее посмотрим пример плохих практик и разберем, почему их стоит избегать.
Магические числа
Возьмем пример программы, которая считает курс валют:
С точки зрения профессиональной разработки, такой код не соответствует «лучшим практикам» — best practices.
В этом примере сложно понять, что значат числа 60 и 1.25 . Представьте, что вам придется разбираться в этом коде через месяц или через год — это будет сложно. Также сложно будет программисту, который не видел код ранее.
В нашем примере контекст легко восстановить, потому что переменные названы грамотно. Но в реальных проектах код значительно сложнее, поэтому понять смысл чисел зачастую невозможно.
Проблема кроется в «магических числах» — magic numbers. Это числа, происхождение которых невозможно понять с первого взгляда — приходится глубоко вникать в то, что происходит в коде.
Чтобы предотвратить проблему, нужно создавать переменные с правильными именами. Так все встанет на свои места:
В этой программе:
- Используется именование snake_case
- Две новые переменные отделяются от последующих вычислений пустой строчкой. Эти переменные имеют смысл и без вычислений, поэтому такое отделение уместно, потому что повышает читаемость
- Получился хорошо именованный и структурированный код, но он длиннее прошлой версии. Так часто бывает — это нормально, ведь код должен быть читабельным
Магические числа и непонятные именования переменных не ломают код, но делают его менее читабельным.
Нужно понимать, что компьютер в любом случае выполнит заданное вычисление. Однако другой программист будет читать код и ничего не поймет — это усложнит работу. Правильное именование переменных — половина успеха анализа кода.
Продвинутый Python: 9 важнейших аспектов при определении классов
![]()
По своей сути, Python является объектно-ориентированным языком программирования, вследствие чего он работает с данными и функциональностями, поддерживая различные объектно-ориентированные возможности. Например, все структуры данных — это объекты, в том числе и примитивные типы, такие как целые числа и строки, которые в других языках к таковыми не относятся. Функции также являются объектами и представляют из себя просто атрибуты других объектов, в которых они определены (например, класса или модуля).
И хотя вы можете использовать встроенные типы данных и писать множество функций, не создавая пользовательских классов, велика вероятность, что по мере роста проекта вам будет все труднее обслуживать код. Эти отдельные фрагменты не имеют общих тематик, и вам придется изрядно потрудиться, чтобы добиться взаимодействия между ними, несмотря на смежность большей части их информации.
В этих сценариях целесообразно определить собственные классы, что позволит сгруппировать схожую информацию и улучшить структурный дизайн проекта. Более того, в перспективе повысится и эффективность обслуживания базы кода, поскольку он будет уже менее фрагментирован. Однако все это осуществимо с одной оговоркой — необходимо правильно определить пользовательский класс, чтобы достигнутые в результате этого преимущества превосходили затраты ресурсов, обусловленные работой с ними.
В данной статье представлен обзор 9 актуальных и наилучших практик, которые стоит рассмотреть применительно к пользовательским классам.
1. Правильные имена
Определяя собственный класс, вы добавляете новое “дитя” в вашу базу кода, так что следует присвоить ему правильное и понятное имя. Несмотря на то, что в Python единственным ограничением при именовании являются правила допустимых имен переменных (например, они не могут начинаться с цифры), существуют ряд предпочтительных способов назвать класс.
- Используйте легко произносимые существительные. Эта рекомендация особенно актуальна при условии совместной работы над проектом. Вряд ли вам захочется оказаться на месте человека, которому во время презентации придется сказать: “В этом случае мы создаем экземпляр класса Zgnehst”. Кроме того, из правила о легко произносимом имени вытекает еще одно, согласно которому оно не должно быть длинным. Сложно представить случаи, когда бы вам потребовалось больше трех слов для определения имени класса. Одно слово — наилучший вариант, два — приемлемый, а три — предельно допустимое количество.
- Отражайте в имени суть содержащихся данных и предполагаемые функциональности. Все как в реальной жизни — мальчиков нарекают мужскими именами. Когда мы слышим имя Максим, то понимаем, что оно принадлежит мальчику. Этот принцип также применим к именам класса (или в целом любой другой переменной). Правило простое — не вводите людей в замешательство! Если вы работаете с информацией о студентах, то классу следует дать соответствующее имя— Student, а не KiddosAtCampus (Парни из универа), которое не несет должной смысловой нагрузки.
- Соблюдайте соглашения об именах. Для именования классов рекомендуется использовать верблюжий стиль (горбатый регистр), например так: GoodName. Далее приводится неполный список неприемлемых имен класса: goodName, Good_Name, good_name и GOodnAme. Следование общепринятым правилам написания имен позволит прояснить ваши намерения. В итоге при чтении кода ни у кого не возникнет сомнения, что объект с именем GoodName является классом.
Существуют также правила и соглашения об именовании атрибутов и функций. Далее я кратко расскажу о них по мере возможности, но в основном принципы те же самые. Просто запомните главное правило: Не вводите людей в замешательство!
2. Явные атрибуты экземпляров
В большинстве случаев наша цель — определить собственный метод инициализации экземпляра, т. е. __init__ . В нем мы устанавливаем начальное состояние создаваемых экземпляров класса. Однако Python не накладывает ограничений относительно того, где в пользовательском классе мы можем определить атрибуты экземпляра. Иначе говоря, вы можете определить дополнительные атрибуты в операциях, следующих за созданием экземпляра. Рассмотрим возможный сценарий в следующем примере кода.
Как показано в примере, можно создать экземпляр класса Student, указав имя и фамилию студента. Далее при вызове метода экземпляра, а именно verify_registration_status , будет установлен атрибут статуса Student. Однако применение такого шаблона нежелательно, поскольку, распространяя различные атрибуты экземпляра по всему классу, вы не даете классу понять, какие данные содержит объект экземпляра. Поэтому будет лучше разместить атрибуты в метод __init__ , чтобы при чтении кода была возможность в одном месте ознакомиться со структурой данных вашего класса. Обратимся к примеру улучшенного метода инициализации.
Если какие-то атрибуты экземпляров нельзя установить изначально, то можно это сделать с помощью значений плейсхолдера, например None . Хотя это и не столь важно, но подобное изменение также помогает предотвратить возможную ошибку, когда вы забываете вызвать методы экземпляра для установки требуемых атрибутов, следствием чего является AttributeError ( ‘Student’ object has no attribute ‘status_verified’ ).
В соответствие с правилами именования атрибуты следует называть, используя строчные буквы и с учетом стиля змеиного регистра, согласно которому составные слова при написании соединяются символом нижнего подчеркивания. Более того, все имена должны передавать суть содержащихся в них данных. Например, вместо fn предпочтительно использовать first_name .
3. Используем свойства, но не увлекаемся
Некоторые учатся программированию на Pyhton, уже владея другими объектно-ориентированными языками, например Java, и привыкли создавать геттеры и сеттеры для атрибутов экземпляров. В Python этот шаблон можно воспроизвести с помощью декоратора property, и в следующем примере мы рассмотрим основной способ его использования для реализации геттеров и сеттеров.
Как только свойство создается, его можно применять в качестве обычных атрибутов, используя точечную нотацию, хотя внутренне оно реализуется с помощью функций.
Скорее всего, вам известно, что в число преимуществ реализации свойств входят проверка правильной установки значений (например, используется ли строка, а не целое число) и доступ только для чтения (без реализации метода setter). Однако использовать их следует в разумных пределах. Такое чрезмерное количество свойств в пользовательском классе, как в нижеприведенном примере, собьет с толку кого угодно!
В большинстве случаев эти свойства вполне заменимы атрибутами экземпляров, вследствие чего мы можем получить к ним доступ и установить их напрямую. В Python предпочтительно использовать атрибуты вместо создания свойств за исключением тех ситуаций, когда вы непосредственно заинтересованы в упомянутых выше преимуществах, таких как проверка значений.
4. Определение содержательных строковых представлений
Функции, содержащие двойные символы нижнего подчеркивания до и после имени, относятся к особым или магическим методам Python. Они используются в специальных случаях для основных операций интерпретатора, включая и ранее рассмотренный метод __init__ . Для создания правильных строковых представлений пользовательского класса необходимы два метода, __repr__ и __str__ , благодаря которым читающие ваш код получат более интуитивно понятную информацию о классах.
Главное их отличие в том, что метод __repr__ определяет строку, с помощью которой вы можете пересоздать объект, вызвав eval(repr(“the repr”)) , тогда как строка, определяемая методом __str__ , является более описательной и предоставляет больше возможностей для кастомизации. Иначе говоря, строка, используемая в методе __repr__ , предназначена для просмотра разработчиками, а строка в методе __str__ — для обычных пользователей. Рассмотрим следующий пример реализации строковых представлений.
Обратите внимание, что при реализации метода __repr__ f-строка использует !r , в результате чего эти строки отображаются в кавычках, поскольку они необходимы для создания экземпляра с правильно отформатированными строками. Без !r -форматирования строка будет выглядеть как Student(John, Smith) , что будет неверным способом создания экземпляра Student. Посмотрим, в каком виде предстают строки в этих реализациях. Если быть более конкретным, то метод __repr__ вызывается при обращении к объекту в интерактивном режиме интерпретатора, а метод __str__ — по умолчанию при выводе объекта.
5.Статические методы, методы экземпляра и класса
В классе мы можем определить 3 вида методов: статические, методы экземпляра и класса. Вы должны решить, какие методы вам нужны для интересующих вас функциональностей. С этой целью предлагаю несколько общих рекомендаций.
В случаях, когда речь идет об отдельных объектах экземпляра, например при необходимости обновления его конкретных атрибутов или обращения к ним, следует задействовать методы экземпляра. Их сигнатура выглядит следующим образом: def do_something(self): , где аргумент self относится к объекту экземпляра, которые вызывает метод.
В других же случаях следует применять статические методы или методы класса. И тот, и другой можно легко определить с помощью соответствующих декораторов: staticmethod и classmethod . Отличаются эти методы тем, что метод классов позволяет вам обратиться к атрибутам класса или обновить их, а статические методы не зависят от экземпляров или самого класса. Типичный пример метода класса — обеспечение удобного способа создания экземпляра, тогда как статический метод может быть просто вспомогательной функцией. В следующем коде приводятся примеры разных видов методов.
Подобным же образом можно создать и атрибуты класса. В отличие от ранее рассмотренных атрибутов экземпляра они совместно используются всеми его объектами и должны отражать некоторые характеристики, независимые от отдельных объектов экземпляра.
6. Инкапсуляция при помощи приватных атрибутов
Создавая пользовательские классы для своих проектов, вы должны принимать во внимание инкапсуляцию, особенно если планируете, что их будут использовать и другие. Когда функциональности класса разрастаются, некоторые функции или атрибуты применимы лишь для обработки данных внутри класса. Иначе говоря, эти функции не будут вызываться за пределами класса, и другие его пользователи не проявят ни малейшего интереса к деталям их реализации. В подобных сценариях вам следует прибегнуть к инкапсуляции.
Для ее применения важно соблюдать соглашение, согласно которому перед атрибутами и функциями ставится одно или два нижних подчеркивания. Тонкое отличие состоит в том, что обладающие одиночным подчеркиванием считаются защищенными, а те, у кого двойное подчеркивание — приватными, что подразумевает правку имени после его создания.
По сути, называя атрибуты и функции подобным образом, вы говорите IDE, например PyCharm, что к ним нельзя получить доступ вне класса, хотя в Python настоящих приватных атрибутов не существует, т. е. при желании можно к ним обратиться.
Данный фрагмент кода содержит простой пример инкапсуляции. Допустим, мы хотим узнать средний балл студента (GPA), что становится возможным с помощью метода get_mean_gpa . Пользователю не нужно знать, как он вычисляется, так что мы можем защитить сопутствующие методы, поставив нижнее подчеркивание перед именами функций.
Ключевая идея этой превосходной практики заключается в том, что вы раскрываете минимальное число общедоступных API, необходимых пользователю для применения вашего кода. В то же время методы, используемые только внутренне, следует сделать защищенными или приватными.
7. Разделение задач и уменьшение зацепления
По мере разработки проекта вы обнаружите, что имеете дело всё с большим числом данных, при этом ваш класс может стать громоздким, если вы привязаны только к нему одному. Рассмотрим проблему на основе примера класса Student. Предположим, что учащиеся обедают в школе, и у каждого из них есть свой счет для оплаты питания. Теоретически мы работаем с данными, связанными с балансом на счете, и функциональностями внутри класса Student, как показано в следующем примере.
Данный пример иллюстрирует псевдокод по проверке баланса счета и его пополнения, при этом обе эти операции реализованы в классе Student. А теперь представьте, что число операций со счетом может увеличиться. Например, добавятся приостановка обслуживания потерянной карты, объединение счетов, и реализация всех из них повлечет за собой всё большее разрастание класса Student, так что со временем обслуживать его станет сложнее. Вместо этого вам следует изолировать эти задачи и снять с класса Student ответственность за связанные со счетом функциональности — в этом суть шаблона проектирования decoupling (уменьшения зацепления).
Этот код показывает, как можно спроектировать структуры данных с помощью дополнительного класса Account. Как видно, мы переместили в него все связанные со счетом операции. Для извлечения необходимых данных класс Student будет обрабатывать функциональность, обращаясь к информации в классе Account. Если мы захотим реализовать больше функций, относящихся к классу, то сможем просто обновить класс Account.
Основная суть этого шаблона проектирования — предоставить конкретным классам возможность решать отдельные задачи. Благодаря этому они становятся компактнее, тем самым облегчая последующие изменения, поскольку число компонентов кода будет уменьшаться.
8. __slots__ для оптимизации
Если ваш класс преимущественно используется в качестве контейнеров только для хранения данных, вы можете рассмотреть __slots__ для оптимизации его производительности. Это позволит не только увеличить скорость доступа к атрибутам, но и экономно расходовать память, что будет как нельзя кстати, если вам потребуется создавать тысячи или более объектов экземпляра. Причина в том, что атрибуты экземпляра для обычного класса хранятся в управляемом изнутри словаре. А вот при задействовании __slots__ они будут сохранены с помощью массивоподобных структур данных, внутренне реализованных с использованием C, что гарантирует оптимизацию их производительности с гораздо большей эффективностью. Перед вами пример использования __slots__ для определения класса:
Данный код показывает простой пример реализации __slots__ в классе. Точнее говоря, вы составляете последовательность из всех атрибутов, которая произведет в хранилище данных сопоставление один-к-одному, ускорив доступ и снизив затраты памяти. Как мы недавно отметили, обычные классы для доступа к атрибутам используют словари, что не касается случаев с реализацией __slots__ . Это демонстрирует следующий пример кода, где в классе со __slots__ отсутствует __dict__:
Однако применение __slots__ сопровождается одним побочным эффектом — оно препятствует динамическому созданию дополнительных атрибутов. Некоторые предлагают использовать его в качестве механизма контроля наличия атрибутов в классе, но это не отвечает его назначению.
9. Документация
Последний, но не менее значимый раздел мы посвятим документации класса. Важно осознать, что факт ее написания не заменит вам код. Тонны документации не повысят его производительность и не улучшат читаемость. Если вам приходится полагаться на строки документации для пояснения кода, то, скорее всего, у него проблемы. Я уверен, что код должен говорить сам за себя. Следующий пример демонстрирует ошибку, которую могут допустить некоторые программисты — ненужные комментарии, компенсирующие плохой код. В данном случае речь идет о бессмысленных именах переменных.
Это совсем не значит, что я против написания комментариев и строк документации — все зависит от конкретных случаев. Если ваш код используется несколькими людьми или по нескольким поводам (например, вы один обращаетесь к коду, но по нескольку раз), то стоит написать к нему хорошие комментарии. Они могут помочь вам или вашим коллегам прочитать код, но никто не должен предполагать, что ваш код делает именно то, что сказано в комментариях. Иначе говоря, написание хорошего кода — это всегда приоритетная задача, о которой нельзя забывать.
Если отдельные фрагменты вашего кода предназначены для конечных пользователей, то необходимо написать строки документации, поскольку эти люди не знакомы с используемой базой кода. Все, что они хотят знать — это как применить интересующий их API, и строки документации в данном случае создадут основу для меню справки. Таким образом, на вас, как на программисте, лежит ответственность за предоставление понятных инструкций по использованию ваших программ.
Заключение
В данной статье был проведен обзор важных факторов, которые следует учитывать при определении собственных классов. Если вы только начинаете изучать Python или программирование в целом, то, возможно, вы до конца не поймете все рассмотренные выше аспекты, но это нормально. Чем больше вы программируете, тем больше осознаете, как важно иметь в виду эти принципы при определении классов. Работая с ними, применяйте данные практики постоянно, так как благодаря хорошему проектированию вы будете тратить все меньше и меньше времени на разработку.
Тест. Python

Чувствителен ли PYTHON к регистру (большая или маленькая буквы):
Варианты ответов
- Да
- Нет
Вопрос 5
Какие существуют типы переменных (выбрать несколько выриантов):
Варианты ответов
- float
- list
- num
- int
- bool
- integer
Вопрос 6
Варианты ответов
- вещественная переменная
- символьная строка
- логическая переменная
- целая переменная
Вопрос 7
Варианты ответов
- символьная строка
- логическая переменная
- целая переменная
Вопрос 8
Варианты ответов
- целая переменная
- вещественная переменная
- логическая переменная
Вопрос 9
Каков будет результат выполнения int("88"):
Варианты ответов
- «88»
- 88
- 88.00
Вопрос 10
Каков будет результат выполнения str(88):
Варианты ответов
- «88»
- 88
- 88.00
Вопрос 11
Имена переменных не могут включать:
Варианты ответов
- Русские буквы
- Латинские буквы
- Пробелы
- Скобки, знаки + = ! ? b др.
Вопрос 12
Какие имена являются правильными в PYTHON (выбрать несколько):
Варианты ответов
- N
- ABC
- sum
- 41And
- A+B
- _mam
Вопрос 13
Что будет в результате выполнения комманды:
Варианты ответов
- 25
- 2500
- 25000
- 1000
Вопрос 14
Что будет в результате следующего действия print(2**20)
Варианты ответов
- 104576
- 1048576
- 964
- 2
Вопрос 15
Что будет в результате выполнения следующего действия print(23 % 2)
Варианты ответов
- 11
- 1
- 0
Вопрос 16
Результатом вычисления print(24 // 3) будет число:
Варианты ответов
- 4
- 8
- 12
Вопрос 17
Что будет результатом выполнения алгоритма:
a = int(input())
b = int(input())
s = a + b
print(s)
Варианты ответов
- 57
- 12
- 35
Вопрос 18
Что будет результатом выполнения алгоритма:
a = input()
b = input()
s = a + b
print(s)
Варианты ответов
- 12
- 57
- 35
Вопрос 19
Что будет в результате выполнения следующего алгоритма:
Входные данные: -57
x = int(input())
if x > 0:
print(x)
else:
print(-x)
Варианты ответов
- -57
- 57
- 0
- -1
Вопрос 20
Что будет в результате выполнения программы:
a = int(input())
b = int(input())
if a < b:
print(a)
else:
print(b)
Варианты ответов
- 10
- 20
- 30
- -10
Вопрос 21
Какой ряд чисел образуется после выполнения следующего алгоритма:
for i in range(1,10):
print(i)
Варианты ответов
- 1 2 3 4 5 6 7 8 9 10
- 1 2 3 4 5 6 7 8 9
- 0
Вопрос 22
Какой ряд чисел образуется после выполнения алгоритма:
for i in range(1,10+1):
print(i)
Варианты ответов
- 1 2 3 4 5 6 7 8 9 10
- 1 2 3 4 5 6 7 8 9 10 11
- 1 4 9 16
Вопрос 23
Что выведет программа после выполнения данного алгоритма:
Входные данные: Иванов
print('Как Ваша фамилия?')
Варианты ответов
- Как Ваша фамилия? Здравствуйте, Иванов!
- Как Ваша фамилия? Здравствуйте, Иванов
- Как Ваша фамилия? Здравствуйте, Иванов !
Вопрос 24
Как обозначается логический оператор И, ИЛИ, НЕ в питоне:
Варианты ответов
- OR, NOT, IF
- AND, OR, NOT
- AND, OR, IF
- AND, ELSE, NOT
Вопрос 25
Что будет в результате выполнения следующего алгоритма программы:
a = int(input())
b = int(input())
if a % 10 == 0 or b % 10 == 0:
print('YES')
else:
print('NO')
Варианты ответов
- YES
- NO
Вопрос 26
Как будет записано число 18 после выполнения следующего алгоритма:
x = float(input())
print(x)
Варианты ответов
- 18
- 18.0
- 18.00
Вопрос 27
Что будет после выполнения следующего листинга программы:
for i in range(4)
print(i)
print(i ** 2)
Варианты ответов
- 0 0 1 1 3 3 4 4
- 0 0 1 1 2 4 3 4
- 0 0 1 1 2 3 3 9
Вопрос 28
Результатом выполнения алгоритма цикла while будет:
i = 1
while i <= 10:
print(i ** 2)
i = i + 1
Варианты ответов
- 1 2 4 8 12 14
- 1 2 16 24 32
- 1 2 4 16 25 36 49 64 81 100
Получите комплекты видеоуроков + онлайн версии








Комментарии 3
Чтобы добавить комментарий зарегистрируйтесь или войдите на сайт
Задания 17 и 18 олинаковые условия, в № 18 по правильным ответам должен стоять знак умножение Задание 23 неверно сделана команда печати
Какие имена переменных можно использовать в Python?
имя переменной может состоять только из цифр, букв и знаков подчеркивания;; имя переменной не может начинаться с цифры. Вдобавок к этим двум .
Какие имена переменных можно использовать в питон?
Правила именования переменных: имя переменной может состоять только из букв, цифр и знака подчёркивания; имя не может начинаться с цифры; имя не может содержать специальных символов @, $, %.
Какие имена являются правильными в питон?
Итак, важнейших правил два:имя переменной может состоять только из цифр, букв и знаков подчеркивания;имя переменной не может начинаться с цифры.Jul 21, 2015
Сколько типов переменных в Python?
В Python поддерживаются 3 разных числовых типа: — целые числа со знаком (int); — значения с плавающей запятой (float); — комплексные числа (complex). В Python 3 все целые числа представлены как long числа, то есть отдельного типа long нет.