Python собака что это
Декораторы в Python: понять и полюбить
Авторизуйтесь
Декораторы в Python: понять и полюбить
Декораторы — один из самых полезных инструментов в Python, однако новичкам они могут показаться непонятными. Возможно, вы уже встречались с ними, например, при работе с Flask, но не хотели особо вникать в суть их работы. Эта статья поможет вам понять, чем являются декораторы и как они работают.
Что такое декоратор?
Новичкам декораторы могут показаться неудобными и непонятными, потому что они выходят за рамки «обычного» процедурного программирования как в Си, где вы объявляете функции, содержащие блоки кода, и вызываете их. То же касается и объектно-ориентированного программирования, где вы определяете классы и создаёте на их основе объекты. Декораторы не принадлежат ни одной из этих парадигм и исходят из области функционального программирования. Однако не будем забегать вперёд, разберёмся со всем по порядку.
Декоратор — это функция, которая позволяет обернуть другую функцию для расширения её функциональности без непосредственного изменения её кода. Вот почему декораторы можно рассматривать как практику метапрограммирования, когда программы могут работать с другими программами как со своими данными. Чтобы понять, как это работает, сначала разберёмся в работе функций в Python.
Как работают функции
Все мы знаем, что такое функции, не так ли? Не будьте столь уверены в этом. У функций Python есть определённые аспекты, с которыми мы нечасто имеем дело, и, как следствие, они забываются. Давайте проясним, что такое функции и как они представлены в Python.
Функции как процедуры
С этим аспектом функций мы знакомы лучше всего. Процедура — это именованная последовательность вычислительных шагов. Любую процедуру можно вызвать в любом месте программы, в том числе внутри другой процедуры или даже самой себя. По этой части больше нечего сказать, поэтому переходим к следующему аспекту функций в Python.
Функции как объекты первого класса
В Python всё является объектом, а не только объекты, которые вы создаёте из классов. В этом смысле он (Python) полностью соответствует идеям объектно-ориентированного программирования. Это значит, что в Python всё это — объекты:
Тот факт, что всё является объектами, открывает перед нами множество возможностей. Мы можем сохранять функции в переменные, передавать их в качестве аргументов и возвращать из других функций. Можно даже определить одну функцию внутри другой. Иными словами, функции — это объекты первого класса. Из определения в Википедии:
Объектами первого класса в контексте конкретного языка программирования называются элементы, с которыми можно делать всё то же, что и с любым другим объектом: передавать как параметр, возвращать из функции и присваивать переменной.
И тут в дело вступает функциональное программирование, а вместе с ним — декораторы.
Функциональное программирование — функции высших порядков
В Python используются некоторые концепции из функциональных языков вроде Haskell и OCaml. Пропустим формальное определение функционального языка и перейдём к двум его характеристикам, свойственным Python:
Функциональному программированию присущи и другие свойства вроде отсутствия побочных эффектов, но мы здесь не за этим. Лучше сконцентрируемся на другом — функциях высших порядков. Что есть функция высшего порядка? Снова обратимся к Википедии:
Функции высших порядков — это такие функции, которые могут принимать в качестве аргументов и возвращать другие функции.
Если вы знакомы с основами высшей математики, то вы уже знаете некоторые математические функции высших порядков порядка вроде дифференциального оператора d/dx. Он принимает на входе функцию и возвращает другую функцию, производную от исходной. Функции высших порядков в программировании работают точно так же — они либо принимают функцию(и) на входе и/или возвращают функцию(и).
Пара примеров
Раз уж мы ознакомились со всеми аспектами функций в Python, давайте продемонстрируем их в коде:
Здесь мы определили простую функцию. Из фрагмента кода далее вы увидите, что эта функция, как и классы с числами, является объектом в Python:
Теперь давайте посмотрим на функции в качестве объектов первого класса.
Мы можем хранить функции в переменных:
Определять функции внутри других функций:
Передавать функции в качестве аргументов и возвращать их из других функций:
Из этих примеров должно стать понятно, насколько функции в Python гибкие. С учётом этого можно переходить к обсуждению декораторов.
Как работают декораторы
Повторим определение декоратора:
Декоратор — это функция, которая позволяет обернуть другую функцию для расширения её функциональности без непосредственного изменения её кода.
Раз мы знаем, как работают функции высших порядков, теперь мы можем понять как работают декораторы. Сначала посмотрим на пример декоратора:
Здесь decorator_function() является функцией-декоратором. Как вы могли заметить, она является функцией высшего порядка, так как принимает функцию в качестве аргумента, а также возвращает функцию. Внутри decorator_function() мы определили другую функцию, обёртку, так сказать, которая обёртывает функцию-аргумент и затем изменяет её поведение. Декоратор возвращает эту обёртку. Теперь посмотрим на декоратор в действии:
Иными словами, выражение @decorator_function вызывает decorator_function() с hello_world в качестве аргумента и присваивает имени hello_world возвращаемую функцию.
И хотя этот декоратор мог вызвать вау-эффект, он не очень полезный. Давайте взглянем на другие, более полезные (наверное):
Здесь мы создаём декоратор, замеряющий время выполнения функции. Далее мы используем его на функции, которая делает GET-запрос к главной странице Google. Чтобы измерить скорость, мы сначала сохраняем время перед выполнением обёрнутой функции, выполняем её, снова сохраняем текущее время и вычитаем из него начальное.
После выполнения кода получаем примерно такой результат:
К этому моменту вы, наверное, начали осознавать, насколько полезными могут быть декораторы. Они расширяют возможности функции без редактирования её кода и являются гибким инструментом для изменения чего угодно.
Используем аргументы и возвращаем значения
В приведённых выше примерах декораторы ничего не принимали и не возвращали. Модифицируем наш декоратор для измерения времени выполнения:
Вывод после выполнения:
Как вы видите, аргументы декорируемой функции передаются функции-обёртке, после чего с ними можно делать что угодно. Можно изменять аргументы и затем передавать их декорируемой функции, а можно оставить их как есть или вовсе забыть про них и передать что-нибудь совсем другое. То же касается возвращаемого из декорируемой функции значения, с ним тоже можно делать что угодно.
Декораторы с аргументами
Мы также можем создавать декораторы, которые принимают аргументы. Посмотрим на пример:
Здесь мы модифицировали наш старый декоратор таким образом, чтобы он выполнял декорируемую функцию iters раз, а затем выводил среднее время выполнения. Однако чтобы добиться этого, пришлось воспользоваться природой функций в Python.
Да, это может быть действительно сложно уместить в голове, поэтому держите правило:
Декоратор принимает функцию в качестве аргумента и возвращает функцию.
Объекты-декораторы
Напоследок стоит упомянуть, что не только функции, а любые вызываемые объекты могут быть декоратором. Экземпляры классов/объекты с методом __call__() тоже можно вызывать, поэтому их можно использовать в качестве декораторов. Эту функциональность можно использовать для создания декораторов, хранящих какое-то состояние. Например, вот декоратор для мемоизации:
Тут будут перечислены некоторые важные вещи, которые не были затронуты в статье или были затронуты вскользь. Вам может показаться, что они расходятся с тем, что было написано в статье до этого, но на самом деле это не так.
Заключение
Надеемся, эта статья помогла вам понять, какая «магия» лежит в основе работы декораторов.
Что такое __init__ в Python?
Чтение по сравнению с другими людьми Python Code, начинающие часто спотыкаются над методом __init __ (Self). Какова его цель? Эта статья отвечает на этот вопрос один раз и для всех.
При чтении кода Python других людей многие новички озадачены __init __ (Я) метод. Какова его цель? Эта статья отвечает на этот вопрос один раз и для всех.
Какова цель __само по себе) в Python?
Зарезервированный метод Python __init __ () называется Конструктор класса. Вы можете вызвать метод конструктора для создания объекта) из класса и инициализировать его атрибуты.
Хотя это отвечает на вопрос, если у вас есть какие-либо амбиции в становлении профессионального Python Coder, этого недостаточно знать, что __init__ Метод – конструктор класса. Вам также необходимо знать, как использовать конструктор в своих собственных проектах – и как настроить его аргументы. Тщательное понимание конструктора служит сильной основой для более продвинутых концепций в объектно-ориентированном программировании Python. Читайте дальше, чтобы узнать другую половину уравнения.
Интерактивный пример Раньше я объясню это вам, давайте откроем свой разрыв в знании. Рассмотрим следующий пример:
Упражнение : Добавьте один цвет аргумента на __в этом__ Способ и сделайте код выполнения без ошибок!
Давайте погрузимся в этот простой пример значительно детально.
Как использовать метод __init__ на практике? Простой пример
Мы будем использовать некоторые условия объектно-ориентированного программирования в Python, чтобы объяснить наш пример. Обязательно изучите следующий чит-лист (вы также можете загрузить PDF здесь). Нажмите на изображение, чтобы получить чит-лист (открывается на новой вкладке). Если вам уже комфортно с базовыми объектами-ориентационными терминами, такими как классы и экземпляры, просто прочитанные.
Вы узнали, что __init__ Метод – это конструктор метода класса. Вы называете метод конструктора для создания новых экземпляров (или объектов ). Но как именно это играет на практике? Прежде чем мы погрузимся в правильное использование, нам нужно понять Аргументы (или Параметры ) метода конструктора.
Самоустройство
__init__ Конструктор требует хотя бы одного аргумента. Согласно Pep8 Standard Хорошая практика для обозначения этого аргумента как Я Отказ В любом случае, Я Аргумент указывает на вновь созданный сам экземпляр, и он позволяет вам манипулировать атрибутами экземпляра нового экземпляра. В приведении собаки вы бы использовали Self.color Чтобы установить недавно созданную собаку цвет атрибут строке «синий» Отказ
Давайте посмотрим на следующий базовый код примера:
Однако этот минимальный пример нереально. Некоторые собаки коричневые, другие черные, и только некоторые голубые.
Множественные аргументы конструктора
В отличие от первого примера, теперь мы определяем конструктор __init __ (я, цвет) с двумя аргументами, а не один.
Обратите внимание, что Я Аргумент неявно обрабатывается средой программирования Python: Python просто передает ссылку на соответствующую Собака Экземпляр к __init__ конструктор.
В чем разница между конструктором и инициатором?
В чем смысл подчеркивает на имя метода __init__?
Я написал целую статью о значении подчеркивания в Python. Проверьте это, если эта тема интересует вас дальше. Ключевой вынос, однако, следующий:
Двойной подчеркивание «__» (называемое «Dunder» ) используется для создания атрибута экземпляра или метод частным (не может быть доступен из-за пределов класса) – при использовании в качестве ведущего разведения. При использовании в качестве приколного разъема (например, «__init__») это указывает на то, что он является специальным методом в Python (называемый «MAGIC MESTORM»).
Как использовать __init__ в унаследованном классе?
Унаследованный класс – это класс, который наследует все атрибуты и методы из родительского класса. Вот пример:
Наследование очень важно в Python. В примере родительский класс является собакой класса, которую вы уже знаете сверху. Метод инициализатора __init__ определяет цвет этой собаки.
Теперь мы также создаем новый класс Cutedog который наследует все атрибуты из родительского класса Собака Отказ Вы можете определить наследование, указав имя родительского класса в скобках после дочернего класса: Cutedog (Собака) Отказ
Интересная вещь состоит в том, что метод __INIT__ для CuteDog Class CuteDog вызывает метод __init__ из родительского класса. Это имеет смысл, потому что у ребенка класс имеет одинаковые атрибуты, что и родительский класс – и их тоже нужно инициализировать.
Чем больше питоновый способ, однако, это использовать Super () Функция, которая облегчает доступ к родительскому классу:
С помощью Super () Функция, вы можете легко повторно использовать метод инициализатора родительского класса.
Давайте посмотрим на несколько связанных вопросов.
__ in init ___ необходимо в Python?
Нет. Вы можете просто пропустить метод инициализатора. В результате ваш класс не будет иметь никаких атрибутов экземпляра непосредственно после его создания. Тем не менее, вы можете добавить атрибуты экземпляра динамически в любой момент времени. Вот пример:
Как красиво! Вы даже можете создавать пустые классы и «заполнить» методы и атрибуты позже в Python.
Что __ init __ возвращение?
То __в этом__ Сам метод ничего не возвращает. Технически, Python впервые использует метод конструктора Собака() до того, как он использует __в этом__ инициализировать все атрибуты. Следовательно, только конструктор возвращает вновь созданный экземпляр.
Может __init__ вернуть значение?
Нет. Единственное возвращаемое значение, которое не вызывает ошибку времени выполнения Никто Отказ Все остальные значения возврата вызывают ошибку. См. В следующем примере кода:
Поэтому никогда не используйте возвращаемое значение в методе __init__, и вы хорошо пойти.
Куда пойти отсюда?
Спасибо за чтение по всей статье. Вы узнали, что __init__ Имя зарезервировано для метода инициализатора Python, который вызывается внутри конструктора.
Статья требует тщательного понимания оснований Python. Инвестирование времени на изучение и изучение тех, кто имеет жизненно важное значение для вашего успеха в качестве профессионального кодера.
Чтобы помочь людям вырастить свои навыки в автоматизированном виде, я создал бесплатный курс по электронной почте Python «Phython Coffee Rapace», который растут вашим уровнем навыка кажутся непременно. День за днем после дня …
Присоединяйтесь к десяткам тысяч кодов Python (100% бесплатно)!
Работая в качестве исследователя в распределенных системах, доктор Кристиан Майер нашел свою любовь к учению студентов компьютерных наук.
Чтобы помочь студентам достичь более высоких уровней успеха Python, он основал сайт программирования образования Finxter.com Отказ Он автор популярной книги программирования Python One-listers (Nostarch 2020), Coauthor of Кофе-брейк Python Серия самооставленных книг, энтузиаста компьютерных наук, Фрилансера и владелец одного из лучших 10 крупнейших Питон блоги по всему миру.
Его страсти пишут, чтение и кодирование. Но его величайшая страсть состоит в том, чтобы служить стремлению кодер через Finxter и помогать им повысить свои навыки. Вы можете присоединиться к его бесплатной академии электронной почты здесь.
Что делает символ » at » ( @ ) в Python?
Я смотрю на некоторый код Python, который использовал @ символ, но я понятия не имею, что он делает. Я также не знаю, что искать, поскольку поиск документов Python или Google не возвращает соответствующих результатов, когда @ символ включен.
10 ответов
на @ символ используется для класса, функции и метода декораторы.
наиболее распространенными декораторами Python, с которыми вы столкнетесь, являются:
преамбула
Я признаю, что мне потребовалось больше нескольких минут, чтобы полностью понять эту концепцию, поэтому я поделюсь тем, что узнал, чтобы избавить других от проблем.
пример
это показывает, что function / method / class вы определяете после оформителя просто в основном передается как argument до function / method сразу после @ знак.
первый прицельный
в microframework колбы представляет декораторы С самого начала в следующем формате:
это в свою очередь переводится как:
осознание этого, наконец, позволило мне почувствовать себя в мире с флягой.
этот фрагмент кода:
эквивалентно этому коду:
в определении декоратора вы можете добавить некоторые измененные вещи, которые обычно не возвращаются функцией.
Это простая реализация матричного умножения.
что делает символ» at » ( @ ) в Python?
короче говоря, он используется в синтаксисе декоратора и для умножения матрицы.
в контексте декораторов, этот синтаксис:
как вы могли обнаружить это самостоятельно?
я также не знаю, что искать, поскольку поиск документов Python или Google не возвращает соответствующие результаты, когда включен символ@.
если вы хотите иметь довольно полное представление о том, что делает конкретный синтаксис python, посмотрите прямо на файл грамматики. Для ветви Python 3:
мы видим здесь, что @ используется в трех контекстах:
Синтаксис Декоратора:
оформителя
синтаксис декоратора-это просто синтаксический сахар, следующие два определения функций семантически эквивалентны:
та же концепция существует для классов, но редко используются там. См. документацию для определений функций и определений классов подробнее о декораторах.
семантически то же самое, что:
они не совсем то же самое, потому что Python оценивает выражение foo (которое может быть пунктирным поиском и вызовом функции) перед баром с декоратором ( @ ) синтаксис, но оценивает выражение foo после bar в другом случае.
(если эта разница имеет значение для вашего кода, Вы должны пересмотреть то, что вы делаете со своей жизнью, потому что это было бы патологическим.)
группа Декораторы
если мы вернемся к документации синтаксиса определения функции, мы увидим:
если мы складываем декораторы, функция, как определено, передается сначала декоратору непосредственно над ним, затем следующему, и так далее.
это о суммирует использование для @ в контексте декораторов.
Оператор @
следующие маркеры являются операторами:
и на следующей странице, модель данных, у нас есть раздел, эмуляция числовых типов,
(Итак, теперь мы узнаем, что @= на месте версия). Далее он объясняет:
умножение Матрицы является особенно распространенной операцией во многих областях математика, наука, инженерство, и добавление @ позволяет написание чистого кода:
умножение матрицы Inplace: @=
исследуя предыдущее использование, мы узнаем, что существует также умножение матрицы inplace. Если мы попытаемся использовать его, мы можем обнаружить, что он еще не реализован для numpy:
когда он будет реализован, я ожидал бы, что результат будет выглядеть так:
что делает символ» at » ( @ ) в Python?
просто decorator позволяет изменять определение данной функции без касания ее внутренней части (это закрытие).
Это самый случай, когда вы импортируете замечательный пакет от третьей стороны. Ты можешь представить это, ты можешь. используйте его, но вы не можете коснуться его сокровенного и его сердца.
вот пример
предположим, я определяю read_a_book функция на Ipython
Как решить такую проблему? Конечно, я мог бы переопределить функцию как:
тем не менее, что делать, если мне не разрешено манипулировать исходной функцией, или если есть тысячи таких функций обрабатываемый.
решить проблему, думая по-другому и определить new_function
тогда используйте его.
Это означает, что вы используете декоратор. Вот пример Брюса Экеля С 2008 года.
сказать, что у других по-другому: да, это декоратор.
в Python это похоже на:
Это можно использовать для всех видов полезного вещи, ставшие возможными, потому что функции-это объекты и просто необходимые инструкции.
Классы Python
Классы в языке Python являются важнейшей частью объектно-ориентированного подхода к программированию. Класс описывает пользовательский тип данных, на основе которого в программе создаются однородные объекты. Как правило, они могут включать в себя некие свойства и методы, позволяющие реализовать их текущее состояние, а также поведение. В статье описаны классы для начинающих и чайников в Python 3, а так же чтобы освежить знания опытным программистам.
Объектно-ориентированное программирование
Объектно-ориентированный подход к разработке ПО был призван стать надежной заменой для структурной методологии программирования. Согласно этой уже устаревшей концепции, каждая отдельно взятая программа является иерархической структурой из функциональных блоков кода.
Благодаря такой особенности:
Основными принципами ООП являются следующие механизмы: абстракция, инкапсуляция, наследование и полиморфизм. Для создания программ, обрабатывающих информацию в виде объектов, необходимо понимание, а также комплексное соблюдение всех четырех парадигм. Практическое применение каждой из них можно встретить в примерах из данной статьи.
Рассмотрим основные принципы ООП:
Создание класса и объекта
Чтобы определить новый класс в своей программе, необходимо напечатать ключевое слово class, а после него добавить имя для создаваемой структуры данных, завершив ввод вставкой двоеточия. Следующий пример демонстрирует генерацию пустого класса с именем Example. Как можно заметить, в нем полностью отсутствует какая-либо информация.
Несмотря на пустое тело класса Example, на его основе уже можно создать определенный объект, обладающий уникальным идентификатором. Последняя строка кода, находящегося выше, представляет собой пример генерации объекта с именем example и типом данных Example. Здесь используется оператор присваивания, а также пустые круглые скобки после названия класса, прямо как в вызове метода не имеющего никаких аргументов.
Определив новый класс, можно создавать сколько угодно объектов на его основе. Как уже было сказано выше, такая структура данных может включать в себя некие свойства, то есть переменные, которыми будет наделен каждый экземпляр класса. Ниже приведен простой пример класса и объекта Python 3. В примере описывается класс под названием Data со строкой word и числом number.
Если создать объект, основанный на классе Data, то он получит обе переменные, а также их значения, которые были определены изначально. Таким образом, был сгенерирован объект data. Получить доступ к его полям с именами word и number можно с помощью оператора точки, вызвав его через экземпляр класса. Функция print поможет вывести значения полей объекта data на экран. Не стоит забывать и о том, что число следует привести к строчному виду для того чтобы обработать его в методе print вместе с текстовым значением.
Помимо полей, пользовательский класс может включать в себя и методы, которыми будут наделены все его экземпляры. Вызвать выполнение определенного метода через созданный объект можно так же, как и получить доступ к его полям, то есть с помощью точки. Данный пример демонстрирует класс Data с функцией sayHello, которая выводит текст на экран.
Для того чтобы вызвать метод sayHello, нужно создать объект, принадлежащий требуемому классу Data. После этого можно запустить функцию через сгенерированный экземпляр с идентификатором data, что позволит вывести небольшое текстовое сообщение.
Аргумент self
Рассмотрим зачем нужен и что означает self в функциях Python. Как можно было заметить, единственным атрибутом для метода из класса является ключевое слово self. Помещать его нужно в каждую функцию чтобы иметь возможность вызвать ее на текущем объекте. Также с помощью этого ключевого слова можно получать доступ к полям класса в описываемом методе. Self таким образом заменяет идентификатор объекта.
Вверху представлен класс Dog, описывающий собаку. Он обладает полями name (имя) со стартовым значением «Charlie» и noise (шум), содержащим звук, который издает животное. Метод makeNoise заставляет собаку лаять, выдавая соответствующее сообщение на экран. Для этого в функции print используется получение доступа к полям name и noise. Далее необходимо создать экземпляр класса Dog и вызвать на нем makeNoise.
Конструктор
В предыдущих примерах кода все создаваемые объекты получали значения для своих полей напрямую из класса, так как они были заданы по умолчанию. Изменить внутренние данные любого объекта можно с помощью оператора доступа к свойствам объекта. Но существует возможность заранее определить поля для объекта, задав их во время его создания. Для этой цели в ООП используется конструктор, принимающий необходимые параметры. Следующий пример показывает работу конструктора во время инициализации объекта класса Dog.
Внешне конструктор похож на обычный метод, однако вызвать его явным образом нельзя. Вместо этого он автоматически срабатывает каждый раз, когда программа создает новый объект для класса, в котором он расположен. Имя у каждого конструктора задается в виде идентификатора __init__. Получаемые им параметры можно присвоить полям будущего объекта, воспользовавшись ключевым словом self, как в вышеописанном примере.
Таким образом, класс Dog содержит два поля: name (имя) и breed (порода). Конструктор принимает параметры для изменения этих свойств во время инициализации нового объекта под названием dog. Каждый класс содержит в себе по крайней мере один конструктор, если ни одного из них не было задано явно. Однако в том случае, когда программист добавляет в свой класс конструктор с некими параметрами, конструктор, не обладающий параметрами, работать не будет. Чтобы им воспользоваться, нужно явно прописать его в классе.
Ключевой особенностью ООП является абстракция, благодаря которой есть возможность создавать частные объекты на основе общего класса, то есть определенного абстрактного понятия, такого как собака, поскольку она может иметь свое имя, породу, вес, рост.
Деструктор
Работа с деструктором, как правило, является прерогативой языков, предоставляющих более широкие возможности для управления памятью. Несмотря на грамотную работу сборщика мусора, обеспечивающего своевременное удаление ненужных объектов, вызов деструктора все еще остается доступным. Переопределить его можно в классе, задав имя __del__.
Как и конструктор, деструктор может содержать некий пользовательский код, сообщающий об успешном завершении работы метода. В данном примере создается экземпляр класса Data и вызывается его деструктор, принимающий в качестве параметра сам объект.
Наследование
Возможность одному классу выступать в качестве наследника для другого, перенимая тем самым его свойства и методы, является важной особенностью ООП.
При наследовании классов в Python обязательно следует соблюдать одно условие: класс-наследник должен представлять собой более частный случай класса-родителя. В следующем примере показывается как класс Person (Человек) наследуется классом Worker (Работник). При описании подкласса в Python, имя родительского класса записывается в круглых скобках.
Person содержит поле name (имя), которое передается классу Worker, имеющему свойство wage (заработная плата). Все условия наследования соблюдены, так как работник является человеком и также обладает именем. Теперь, создав экземпляр класса Worker под названием human, можно получить свободный доступ к полям из родительской структуры данных.
Множественное наследование
Наследовать можно не только один класс, но и несколько одновременно, обретая тем самым их свойства и методы. В данном примере класс Dog (Собака) выступает в роли подкласса для Animal (Животное) и Pet (Питомец), поскольку может являться и тем, и другим. От Animal Dog получает способность спать (метод sleep), в то время как Pet дает возможность играть с хозяином (метод play). В свою очередь, оба родительских класса унаследовали поле name от Creature (Создание). Класс Dog также получил это свойство и может его использовать.
В вышеописанном примере создается объект класса Dog, получающий имя в конструкторе. Затем по очереди выполняются методы sleep (спать), play (играть) и bark (лаять), двое из которых были унаследованы. Способность лаять является уникальной особенностью собаки, поскольку не каждое животное или домашний питомец умеет это делать.
Абстрактные методы
Поскольку в ООП присутствует возможность наследовать поведение родительского класса, иногда возникает необходимость в специфической реализации соответствующих методов. В качестве примера можно привести следующий код, где классы Dog (Собака) и Cat (Кошка) являются потомками класса Animal (Животное). Как и положено, они оба наследуют метод makeNoise (шуметь), однако в родительском классе для него не существует реализации.
Все потому, что животное представляет собой абстрактное понятие, а значит не способно издавать какой-то конкретный звук. Однако для собаки и кошки данная команда зачастую имеет общепринятое значение. В таком случае можно утверждать, что метод makeNoise из Animal является абстрактным, поскольку не имеет собственного тела реализации.
Как видно из примера, потомки Dog и Cat получают makeNoise, после чего переопределяют его каждый по-своему. В этом заключается суть полиморфизма, позволяющего изменять ход работы определенного метода исходя из нужд конкретного класса. При этом название у него остается общим для всех наследников, что помогает избежать путаницы с именами.
Статические методы
В вышеописанном коде класс Math включает в себя два статических метода: inc, берущий число в качестве параметра и возвращающий результат, увеличенный на единицу, и dec, делающий все то же самое, только наоборот. Вызвать оба этих метода можно с помощью оператора точки, а также имени класса Math, где они были изначально реализованы.
Ограничение доступа
По умолчанию все свойства классов открыты для доступа извне, благодаря чему их можно в любой момент изменить по своему усмотрению при помощи оператора точки. Это не всегда хорошо, так как существуют некие риски потери информации либо введения неправильных данных, приводящих к сбоям в работе программы. Особенно это опасно, когда над проектом работает несколько программистов и не всегда очевидно, для чего нужно то или иное поле.
В такой ситуации помогает еще одна особенность ООП под названием инкапсуляция. Она предписывает применение приватных свойств класса, к которым отсутствует доступ за его пределами. Для управления содержимым объекта необходимо использовать специальные методы, именуемые getter (возвращает значение) и setter (устанавливает значение).
Чтобы ограничить видимость полей, следует задать для них имя, начинающееся с двойного подчеркивания. В примере, продемонстрированном выше, класс Cat (Кошка) имеет закрытое свойство __name (имя), а также специальные методы get_name и set_name. Отличительной чертой такого подхода является возможность установить определенные рамки для вводимых значений. Например, можно запретить ввод отрицательного числа или пустой строки.
Свойства классов
С помощью специального механизма свойств класса можно внести корректировки в работу с оператором точки, присвоив ему собственные функции. В следующем примере представлен класс с приватным полем x, для которого написаны getter и setter. С помощью присвоения полю x специального значения функции property, получающей в качестве аргументов имена методов, можно настроить работу оператора точки согласно своим нуждам.
Перегрузка операторов
Для обработки примитивных типов данных в языках программирования используются специальные операторы. К примеру, арифметические операции выполняются при помощи обычных знаков плюс, минус, умножить, разделить. Однако при работе с собственными типами информации вполне может потребоваться помощь этих операторов. Благодаря специальным функциям, их можно самостоятельно настроить под свои задачи.
В данном примере создается класс Point (точка), обладающий двумя полями: x и y. Для сравнения двух разных объектов такого типа можно написать специальный метод либо же просто перегрузить соответствующий оператор. Для этого потребуется переопределить функцию __eq__ в собственном классе, реализовав новое поведение в ее теле.
Переопределенный метод возвращает результат сравнения двух полей у различных объектов. Благодаря этому появилась возможность сравнивать две разных точки, пользуясь всего лишь обычным оператором. Результат его работы выводится при помощи метода print.
Аналогично сравнению, можно реализовать в Python перегрузку операторов сложения, вычитания и других арифметических и логических действий. Так же можно сделать перегрузку стандартных функций str и len.
Заключение
В данной статье были рассмотрены основные особенности работы с классами в языке Python и наглядно продемонстрированы наиболее важные принципы объектно-ориентированного программирования. Работа с классами позволяет представить все данные в программе в виде взаимодействующих между собой объектов, обладающих некими свойствами и поведением.