Питон ооп: концепции, принципы и примеры реализации

Содержание

Почему в Python плохой ООП / Хабр

В Python ужасный ООП. Кликбейтный тезис, который имеет право на существование. Есть много языков, где ООП представлен не в самом классическом виде, ну или так принято считать. Прототипные JavaScript и Lua, Golang с прикреплением методов и прочие. Но «не такой как все» всегда ли синоним слова «неправильный»?  С чего мы вообще вязли, что ООП в Python не такой каким должен быть ООП? Что вообще является точкой отсчёта «правильности» ООП? Smalltalk или Simula 67? Вроде бы объектно-ориентированное программирование – это просто парадигма.. или уже догма?

В этом статье мы попробуем понять:

  • что не так с ООП в Python;

  • чем его ООП отличается от языков с эталонной по мнению многих реализацией ООП: Java, C# и С++;

  • почему разработчики языка Python решили сделать всё именно так.

Реализует этот текст автор YouTube-канала PyLounge Макс. Поехали!

Дисклеймер: В этой статье я хочу высказать свои «рассуждения на тему» и подчёркиваю, что не обладаю монополией на истину. Буду рад осудить альтернативное мнение в комментариях.

Для начала необходимо понять. Чем ООП в Python отличается от классической концепции и реализации в других ЯП.

Парадигма ООП появилась ещё 60-70-х годах XX века. ООП или Объектно-ориентированное программирование — это методология программирования, которая основана представлении программы в виде набора взаимодействующих объектов, каждый из которых является экземпляром класса, а классы образуют иерархию наследования.

Ключевыми особенностями ООП является понятия:

  • абстракция; 

  • инкапсуляция; 

  • наследование; 

  • полиморфизм.

Алан Кэй, создателя языка Smalltalk, одним из «отцов-основателей» ООП, говорил, что ООП подход заключается в следующем наборе принципов:

  1. Всё является объектом.

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

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

  4. Каждый объект является представителем класса, который выражает общие свойства объектов (таких, как целые числа или списки).

  5. В классе задаётся поведение (функциональность) объекта. Тем самым все объекты, которые являются экземплярами одного класса, могут выполнять одни и те же действия.

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

«ООП для меня означает лишь обмен сообщениями, локальное сохранение, и защита, и скрытие состояния, и крайне позднее связывание». (c) Алан Кэй

Другими словами, в соответствии с идеями Алана Кэя, самыми важными ингредиентами ООП является:

  1. Передача сообщений (то есть взаимодействие).

  2. Инкапсуляция.

  3. Динамическое связывание.

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

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

Все остальное же было определено, когда появились объектно-ориентированные языки. Языки OO были разработаны, чтобы упростить подход к программированию. И они реализовали инструменты и функции для поддержки ООП — классы были одним из таких инструментов.

Под инкапсуляцией стали подразумевать возможность классов содержать данные и методы в себе, которые непосредственно связаны с этим классом по смыслу.  При этом одни языки соотносят инкапсуляцию с сокрытием этой информации, а другие (Smalltalk, Eiffel, OCaml) различают эти понятия.

Например, в Java можно определить поле как приватное, и тогда оно будет видно только членам этого класса. Также работает и С++, однако там есть концепция друзей (friend), которые могут видеть приватные поля других классов, что сильно критикуется.

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

Полиморфизм — это возможность обработки разных типов данных, т. е. принадлежащих к разным классам, с помощью «одной и той же» функции, или метода. На самом деле одинаковым является только имя метода, его исходный код зависит от класса. Поэтому в данном контексте под полиморфизмом понимается множество форм одного и того же слова – имени метода.

Абстрагирование (абстракция данных) означает выделение значимой информации и исключение из рассмотрения незначимой. В ООП рассматривают абстракцию данных, подразумевая набор наиболее значимых характеристик объекта, доступных остальной программе.

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

В центре ООП находится понятие объекта. Объект — это сущность, которой можно посылать сообщения и которая может на них реагировать, используя свои данные. Объект — это экземпляр класса. Данные объекта содержатся в объекте, а не просто лежат внутри программы. Инкапсуляция включает в себя сокрытие (но им не является!).

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

Современная идея ООП — это синтез всех их идей, а также идей Голдберга, Барбары Лисков, Дэвида Парнаса, Бертрана Мейера, Гюля Ага и других. Но никто из них не может утверждать, что же такое «ООП». Термины развиваются, как и задачи, которые изначально эти инструменты должны были решать.

А что же касаемо Python. Python полностью удовлетворяет всем перечисленным выше требования, а значит является «полностью объектно-ориентированным». ООП – просто стиль.

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

Отсутствие модификаторов доступа

В Python отсутствует деление на публичные, защищённые, приватные свойства и методы.   Многие вещи в Python основаны на соглашениях. Сокрытие данных реализуется чисто конвенционально. За счёт соглашения использовать подчёркивание у свойств и методов (защищённые члены). Да, можно использовать двойное подчёркивание, так называемый манглинг. Чисто технически это запрещает прямой доступ к данным и равносильно модификатору приват, но это скорее придуманный адептами классического ООП «грязный хак». Таким образом, в Python нет классического разделения на группы доступа, потому что Python доверяет разработчику. В этом плане Python ближе к С++.

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

Мне кажется, инкапсуляция не так полезна в языке с динамической типизацией.  Выскажу непопулярное мнение – это не добавляет никакой безопасности, она просто дает ощущение безопасности. Если вы грамотный программист, то так или иначе сделаете всё как надо.

Но почему разработчики языка не добавили такой привычный «предохранитель»? Ответ кроется в философии Python. Гвидо не любит что-то скрывать. Как он выразился в одном интервью: «мы все здесь взрослые по обоюдному согласию. Python доверяет вам. Он говорит: «Эй, если хочешь чтобы ковыряться в темных местах, я надеюсь, что у тебя есть уважительная причина, и вы не создаете проблем». Этого тезиса мы ещё коснёмся ниже. Пока просто запомните.

Вообще инкапсуляция – это не совсем про сокрытие. Инкапсуляция определяется как «процесс объединения элементов данных и функций в единое целое, называемое классом» или «отделение реализации от описания». Таким образом, номинально в Python всё соблюдается более чем верно.

Отсутствие интерфейсов

В языке Python нет как таковой конструкции как интерфейс (interface). К слову в С++ их тоже нет. Но что в Python, что в С++, есть механизмы, позволяющие так или иначе использовать интерфейсы.  Абстрактные классы ­– это хоть и немного другое, но функционалу отвечает и допускает некоторое упрощение концепции. На мой взгляд, отсутствие интерфейсов искусственный механизм избежания неоднозначности. Вот у тебя есть абстрактные классы, вот их и используй. С помощью абстрактных классов можно сделать всё тоже что и с интерфейсами, но не надо заморачиваться. Ведь Python идёт по пути простоты и убирает всё лишнее. Создатели языка даже конструкцию switch case выкинули, дабы «место не занимала».

Множественное наследование

Многие современные языки отказываются от множественного наследования, так как оно многое усложняет. Однако Python хоть и идёт по пути упрощения, но старается выкидывать избыточность, а не функциональность, ведь любое упрощение — это потеря гибкости + см. пункт про доверие своему разработчику. Python думает, что разработчик, который его использует достаточно умён, чтобы не плодить гигантскую иерархию и победить проблему ромба. Не доверился он разве что, при создании GIL. Но спишем это на ошибки молодости. Кстати, С++ также поддерживает множественное наследование. Так что с этим пунктом всё тоже в рамках закона.

Утиная типизация

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

Если что-то выглядит как утка, плавает как утка и крякает как утка, это наверняка и есть утка.

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

Тут во всей красе демонстрируется один из главных принципов Дзена Python«явное лучше, чем неявное». Если что-то выглядит как утка и крякает, то это утка, к чему погружаться в экзистенциальные копания и вопросы самоопределения? Будь проще и посмотри пример.

Поскольку Duck и Human это разные классы, Python повторно вызывает функцию fly_quack() для экземпляра класса Human. И хотя класс Human имеет похожие методы quack и fly , типы объектов были разными и поэтому все работает правильно и вызываются верные методы.

Константные методы

Нет способов предотвратить изменение состояния класса методами класса (константные методы), снова всё полагается на добрую волю программиста.

Вообще докопаться ещё можно много до чего. Например, не совсем стандартное описание статических методов и свойств, параметр self, MRO и многое многое другое.

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

The Zen of Python

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

По мнению многих Smalltalk — самый чистый ООП язык, но что даёт и какова цена этой чистоты? Можно написать очень хороший объектно-ориентированный код как на Smalltalk, так и на Python.

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

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

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

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

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

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

ООП в Python не лучше и не хуже, чем в других языка. Он другой. Такой каким концептуально его видел главный разработчик языка Гвидо ван Россум. ООП в Python это часть Дзена Python. Философии, для которой язык и был разработан.

Проблема в том, что люди пытаются перенять подходы из других языков, а не учатся использовать уникальные сильные стороны Python. У Python довольно надежная объектная модель, но это объектная модель Python, а не C++, Java или…кого-то другого.

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

А Python просто сейчас очень популярен. Он своего рода фронтмен, а тот кто на передовой, того обычно и критикуют. И да, я понимаю, что Python стремится быть как можно более простым, как завещал Эйнштейн: «все должно быть настолько простым, насколько это возможно, но не проще». Однако иногда Python всё же попадает в это «проще» чем надо, что может выливаться в проблемы.

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

Дизайн языка потихоньку меняется. Аннотации типов, разного рода оптимизации говорят о том, что язык и сообщество взрослеют и зреют. Python со времён 2 версии уже сильно изменился и будет продолжать меняться. Как молодой бунтарь контркультуртурщик под призмой времени превращается в консерватора и прагматика, также и Python превратится просто в стабильный качественный инструмент. А на смену ему придёт новая рок-звезда, которая будет вертеть устои инженерной культуры и привлекать школьников.

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

Если мы напишем язык, который смогут использовать идиоты, в конце концов, только идиоты и будут его использовать. И да, это цена, которую придётся заплатить.


Закончу мысль довольно известной фразой: «Есть всего два типа языков программирования: те, на которые люди всё время ругаются, и те, которые никто не использует».

Добрый, добрый Python ООП — обучающий курс от Сергея Балакирева — Stepik

Начните увлекательное путешествие в мир объектно-ориентированного программирования (ООП) на языке Python! Здесь вы сможете с нуля, с самого начала постичь магию объектно-ориентированного программирования. Увидите, как концепция классов и объектов позволяет заметно упрощать структуру программ, делать их более…

What you will learn

  • 1. Понимать общий принцип ООП, его отличие от функционального программирования.
  • 2. Сможете использовать подход ООП при разработке собственных программ.
  • 3. Узнаете особенности реализации ООП на языке Python.
  • 4. Изучите все основные магические методы классов языка Python.
  • 5. Подробно познакомитесь с наследованием и полиморфизмом.
  • 6. Научитесь применять обработку исключений и менеджеры контекстов в своих проектах.

About this course

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

В курсе пошагово, начиная с самых простых конструкций (классов, объектов, методов), вы будете погружаться в увлекательный мир ООП. Вначале каждого урока дается теоретический видео-материал, который, затем, закрепляется набором практических заданий (подвигов). В конце некоторых разделов предлагается пройти испытание — разработка полноценной программы, которая позволяет в полной мере соприкоснуться с ООП.

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

Телеграм-канал для обсуждения: https://t.me/python_selfedu

Whom this course is for

Этот курс — продолжение курса «Добрый, добрый Python» (https://stepik.org/course/100707/), который был посвящен основам языка Python. Если вы его не проходили, или плохо владеете базовыми конструкциями программирования на Python, то рекомендуется сначала ознакомиться с базой языка, а уже затем, переходить на следующий уровень ООП.

Initial requirements

Знание базовых основ языка Python (для их изучения пройдите курс «Добрый, добрый Python» (ссылка: https://stepik.org/course/100707/)

Meet the Instructors

Course content

Certificate

Stepik certificate

Price

FAQ

How to purchase the course in installments?

How to pay from the company?

Share this course

https://stepik. org/course/116336/promo

Direct link:
https://stepik.org/116336

Объектно-ориентированное программирование на Python: Учитесь на примерах

В этом руководстве рассказывается об объектно-ориентированном программировании (ООП) на Python с примерами. Это пошаговое руководство, предназначенное для людей, не имеющих опыта программирования. Объектно-ориентированное программирование популярно и доступно на других языках программирования, помимо Python, таких как Java, C++, PHP.

Что такое объектно-ориентированное программирование?

В объектно-ориентированном программировании (ООП) у вас есть возможность представлять в своем коде объекты реального мира, такие как автомобиль, животное, человек, банкомат и т. д. Простыми словами, объект – это то, что обладает некоторыми характеристиками и может выполнять определенные функции. Например, автомобиль является объектом и может выполнять такие функции, как запуск, остановка, движение и торможение.

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

В приведенном выше примере автомобиль является объектом . Функции называются методами в мире ООП. Характеристики атрибутов (свойств) . Технически атрибуты — это переменные или значения, связанные с состоянием объекта, тогда как методы — это функции, которые влияют на атрибуты объекта.

В Python все является объектом. Строки, целые числа, числа с плавающей запятой, списки, словари, функции, модули и т. д. — все это объекты.

Используют ли специалисты по данным объектно-ориентированное программирование?

Это один из самых распространенных вопросов, который возникает у ученых, занимающихся данными, перед изучением ООП. Когда дело доходит до манипулирования данными и машинного обучения с использованием Python, обычно рекомендуется изучать библиотеки pandas, numpy, matplotlib, scikit-learn. Эти библиотеки были написаны опытными разработчиками Python для автоматизации или упрощения большинства задач, связанных с наукой о данных. Все эти библиотеки зависят от ООП и его концепций. Например, вы строите регрессионную модель, используя библиотеку scikit-learn. Сначала вы должны объявить свою модель как объект, а затем использовать метод подгонки. Без знания основ ООП вы не сможете понять, почему вы пишете код таким образом.

В python в основном существует 3 стиля программирования: объектно-ориентированное программирование, функциональное программирование и процедурное программирование. Проще говоря, есть 3 разных способа решения проблемы в Python. Функциональное программирование наиболее популярно среди специалистов по данным, поскольку оно имеет преимущество в производительности. ООП полезен, когда вы работаете с большими кодовыми базами, а ремонтопригодность кода очень важна.

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

Основы: ООП в Python

В этом разделе мы подробно рассмотрим концепции, связанные с ООП в Python.

Объект и класс

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


Существует множество реальных примеров классов, описанных ниже —

  • Рецепт омлета — это класс. Омлет — это объект.
  • Владелец банковского счета — это класс. Атрибутами являются Имя, Фамилия, Дата рождения, Профессия, Адрес и т. д. Методы могут быть «Смена адреса», «Смена профессии», «Смена фамилии» и т. д. «Смена фамилии» обычно применима к женщины, когда они меняют фамилию после замужества
  • Собака — это класс. Атрибуты: Порода, Количество ног, Размер, Возраст, Цвет и т. д. Методы могут быть Едят, Спят, Сидят, Лают, Бегают и т. д.

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

Пример 1: Создать класс автомобиля

  • класс : автомобиль
  • атрибуты : год, мили на галлон и скорость
  • методы : ускорение и торможение
  • объект : автомобиль1
класс автомобиля:
    
    # атрибуты
        year = 2016 # год выпуска модели автомобиля
        миль на галлон = 20 # пробег
        скорость = 100 # текущая скорость
        
    # методы
        Ускорение по определению (само):
            вернуть автомобиль.
скорость + 20 деф тормоз(сам): скорость возврата автомобиля - 50
автомобиль1=автомобиль()
car1.ускорить()
120
car1.тормоз()
50
автомобиль1.год
2016
машина1.миль на галлон
20
автомобиль1.скорость
100
 

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

Пример 2: Создание класса компании

В приведенном ниже примере мы создаем класс с именем company. Здесь атрибутами являются название, оборот, выручка и количество сотрудников, работающих в компании. Метод — доход, полученный на одного работника (назовем его производительность для демонстрационных целей).

# Создает класс Company
класс Компания:
    
    # атрибуты
    имя = "Банк XYZ"
    оборот = 5000
    доход = 1000
    количество_сотрудников = 100
    
    # метод
    Производительность по определению (я):
        вернуть Company.revenue/Company.no_of_employees
 

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

Название компании
  Выход 
«XYZ Банк»
Компания.оборот
  Выход 
5000
Company.no_of_employees
  Выход 
100
Компания().производительность()
  Выход 
10,0
 

Конструктор

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

Объекты являются экземплярами класса. Слова «экземпляр» и «объект» взаимозаменяемы. Процесс создания объекта класса называется экземпляр .

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

классный человек:
        def __init__(я,имя,фамилия):
            self.first = имя
            self.last = фамилия
мое имя = человек ("Дипаншу", "Бхалла")
распечатать (мое имя.последнее)
 
Мы создали myname объект класса person.
 При создании нового объекта >>> вызывается метод __init__ >>> Поведение внутри метода __init__ выполняется 

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

.
класс Моя компания:
        
    # методы
    def __init__(я, название компании, доход, размер сотрудников):
        self.name = название компании
        собственный доход = доход
        self.no_of_employees = количество сотрудников
    Производительность по определению (я):
        вернуть self.revenue/self.no_of_employees
Моя компания('Банк XYZ', 1000,100).производительность()
  Выход 
10,0
MyCompany('ABC Bank', 5000,200). productivity()
  Выход 
25,0
 

Альтернативный способ вызова метода класса

Банк = MyCompany('ABC Bank', 5000,200)
MyCompany.productivity(Банк)
 

Переменные

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

При использовании метода __int__ доступ к переменным возможен только после создания объекта. Эти переменные называются Переменные экземпляра или локальные переменные. Тот, который определен вне методов, называется переменными класса или глобальными переменными. Вы можете получить доступ к этим переменным в любом месте класса. Посмотрите разницу в примере ниже.

класс Моя компания:
    #Переменная класса
    рост = 0,1
            
    def __init__(я, название компании, доход, размер сотрудников):
        #Переменные экземпляра
        self. name = название компании
        собственный доход = доход
        self.no_of_employees = количество сотрудников
МояКомпания.рост
  0,1 
 

Как получить переменную дохода из класса MyCompany?

Неправильный путь

Моя компания.доход
 

AttributeError: объект типа «Моя компания» не имеет атрибута «доход»

Правильный путь

Банк = МояКомпания('Банк DBA',50000, 1000)
Банк.доход
 

50000

MyCompany.revenue возвращает ошибку, поскольку к ней невозможно получить доступ, поскольку объект не создан.

Методы

В python есть три типа методов: экземпляр, класс и статический.

  • Экземпляр принимает self в качестве первого аргумента. Их также называют Object или обычным методом . Это тот же метод, который мы уже изучили в предыдущих разделах.
  • Класс принимает cls в качестве первого аргумента. cls относится к классу. Чтобы получить доступ к переменной класса в методе, мы используем @classmethod 9декоратор 0010 и передать класс методу
  • Статический ничего не принимает в качестве первого аргумента. Он имеет ограниченное использование, которое объясняется в последней части этой статьи.

Чем отличаются методы экземпляра и класса?

Метод экземпляра может получить доступ к свойствам, уникальным для объекта или экземпляра. Принимая во внимание, что метод класса используется, когда вы хотите получить доступ к свойству класса, а не к свойству конкретного экземпляра этого класса. Другое отличие с точки зрения стиля написания заключается в том, что метод экземпляра принимает self в качестве первого параметра, тогда как метод класса принимает cls в качестве первого параметра.

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

Здесь мы создаем 3 метода: rateperkm , noofcabs , avgnoofpassengers . Первый — это метод экземпляра, а два других — методы класса.

  • рейтперкм возвращает стоимость проезда в такси за км, которая рассчитывается путем деления общей суммы счета на номер. км пройдено кабиной.
  • noofcabs возвращает количество работающих кабин. Подумайте об агентстве такси, которое владеет множеством такси и хочет знать, сколько такси занято
  • .
  • avgnoofpassengers возвращает среднее количество пассажиров, путешествующих в автомобиле. Для расчета среднего значения учитываются все работающие кабины и количество пассажиров в каждой кабине.
Кабина класса:
    
    #Инициализировать переменные для первой итерации
    количество кабин = 0
    количество пассажиров = 0
    def __init__(я,водитель,км,места,оплата,пассажиры):
        self.driver = водитель
        автономный пробег = км
        self.places = места
        селф.билл = платить
        Cab.numberofcabs = Cab.numberofcabs + 1
        Cab.numpassengers = Cab.numpassengers + пассажиры
    #Возвращает цену такси за км
    def rateperkm(я):
        возврат self.bill/self.running
        
    #Возвращает количество запущенных кабин
    @классметод
    определение noofcabs (cls):
        вернуть cls.numberofcabs
    #Возвращает среднее количество пассажиров в кабине
    @классметод
    определение avgnoofpassengers (cls):
        вернуть целое (cls.numpassengers/cls.numberofcabs)
firstcab = Cab("Рамеш", 80, ['Дели', 'Нойда'], 2200, 3)
secondcab = Cab("Суреш", 60, ['Гургаон', 'Нойда'], 1500, 1)
Thirdcab = Cab("Дэйв", 20, ['Гургаон', 'Нойда'], 680, 2)
firstcab. водитель
  'Рамеш'
 
водитель второго такси
  'Суреш'
 
третий каб.водитель
  'Дэйв'
  
firstcab.rateperkm()
  27,5 
secondcab.rateperkm()
  25,0 
Thirdcab.rateperkm()
  34,0 
 
Кабина.noofcabs()
  3
 
Cab.avgnoofpassengers()
  2
  
Cab.avgnoofpassengers() возвращает 2, что вычисляется как (3 + 1 + 2)/3

Статические методы

Статический метод является наименее популярным среди всех трех методов. В отличие от методов экземпляра и класса, статический метод не принимает в качестве первого параметра специальное ключевое слово (self, cls). Он имеет ограниченное использование, потому что ни вы не можете получить доступ к свойствам экземпляра (объекта) класса, ни вы не можете получить доступ к атрибутам класса. Единственное использование - его можно вызывать без объекта. Это в основном полезно для создания вспомогательных или служебных функций, таких как проверка имени водителя (имя водителя должно быть меньше 32 символов) или сумма счета должна быть больше нуля (не может быть отрицательной или нулевой). См. программу ниже для той же задачи.

Кабина класса:
    
    @статический метод
    деф биллинга (оплата):
        возврат int (оплата)> 0
Cab.billvalidation(0,2)
  Выход 
ЛОЖЬ
 

Наследство

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

  • Создать родительский класс Vehicle и использовать его атрибуты для дочернего класса Vehicle . В приведенной ниже программе нам не нужно указывать атрибуты класса cab. Он наследуется от транспортного средства.
класс Транспортное средство:
    def __init__(я,водитель,колеса,сиденья):
        self.driver = водитель
        self.noofwheels = колеса
        self.noofseats = места
класс Кабина(Автомобиль):
    проходить
cab_1 = Кабина («Сэнди», 4, 2)
кабина_1.водитель
  Выход 
'Сэнди'
 
  • Как изменить переменную класса подкласса Транспортное средство
  • класс Транспортное средство:
        минимальная ставка = 50
        def __init__(я,водитель,колеса,сиденья):
            self.driver = водитель
            self.noofwheels = колеса
            self.noofseats = места
    класс Кабина(Автомобиль):
        минимальная ставка = 75
    Транспортное средство.минимальная ставка
      50 
    Минимальная ставка кабины
      75 
     
  • Как создать дочерний класс с большим количеством параметров, чем у родительского класса
  • В этом примере у нас есть два класса Cab и Bus , у которых много схожих атрибутов, но есть несколько уникальных для данного класса. Чтобы решить эту проблему, мы создали родительский класс с именем Vehicle , который содержит общие атрибуты и метод.

    класс Транспортное средство:
        минимальная ставка = 50
        def __init__(я,водитель,колеса,сиденья,км,счет):
            self.driver = водитель
            self.noofwheels = колеса
            self.noofseats = места
            автономный пробег = км
            селф.билл = счет
        
        def rateperkm(я):
            возврат self.bill/self.running
    класс Кабина(Автомобиль):
        минимальная ставка = 75
        def __init__(я,водитель,колеса,сиденья,км,счет,тип кабины):
            Vehicle.__init__(я,водитель,колеса,сиденья,км,счет)
            self.category = тип такси
    Класс Автобус(Автомобиль):
        минимальная ставка = 25
        def __init__(я,водитель,колеса,сиденья,км,счет,цвет):
            Vehicle.__init__(я,водитель,колеса,сиденья,км,счет)
            self.color = цвет
    cab_1 = Cab('Prateek', 4, 3, 50, 700, 'Внедорожник')
    cab_1.категория
    cab_1.rateperkm()
    bus_1 = Bus('Дэйв', 4, 10, 50, 400, 'зеленый')
    bus_1. цвет
    bus_1.rateperkm()
     
    Мы можем заменить эту команду Vehicle.__init__(я,водитель,колеса,сиденья,км,счет) на super().__init__(водитель,колеса,сиденья,км,счет) .
    super() используется для ссылки на родительские атрибуты и методы.

    Полиморфизм

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

    Переопределение метода

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

    класс Транспортное средство:
        защитное сообщение (я):
            print("Метод родительского класса")
    класс Кабина(Автомобиль):
        защитное сообщение (я):
            print("Метод класса дочерней кабины")
    Класс Автобус(Автомобиль):
        защитное сообщение (я):
            print("Метод класса дочерней шины")
    х = Транспортное средство ()
    х. сообщение()
      Метод родительского класса 
    у = кабина ()
    у.сообщение()
      Метод класса Child Cab 
    г = автобус ()
    z.сообщение()
      Метод класса дочерней шины 
     

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

    Перегрузка метода

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

    В приведенном ниже сценарии метод может быть вызван без параметра (игнорируя параметр фразы). Или его можно вызвать с параметром , фразой .

    Сообщение класса:
        детали защиты (я, фраза = нет):
        
            если фраза не None:
                print('Мое сообщение - ' + фраза)
            еще:
                print('Добро пожаловать в мир Python')
            
    # Объект
    х = сообщение ()
        
    # Вызов метода без параметров
    х. детали()
        
    # Вызов метода с параметром
    x.details('Жизнь прекрасна')
     

    Что такое __str__?

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

    класс Транспортное средство:
        def __init__(я,водитель,колеса,сиденья):
            self.driver = водитель
            self.noofwheels = колеса
            self.noofseats = места
    veh_1 = Автомобиль ("Песчаный", 4, 2)
    печать (veh_1)
      Выход 
     __main__.Объект транспортного средства по адресу 0x0000019ECCCA05F8
     
    класс Транспортное средство:
        def __init__(я,водитель,колеса,сиденья):
            self.driver = водитель
            self.noofwheels = колеса
            self.noofseats = места
        защита __str__(я):
            return "Имя водителя:" + self.driver + ";" + "Количество мест в кабине:" + str(self.noofseats)
    veh_1 = Автомобиль ("Песчаный", 4, 2)
    печать (veh_1)
      Выход 
    Имя водителя: Сэнди;
    Количество мест в кабине: 2
     

    Инкапсуляция данных

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

    • Когда мы используем два символа подчеркивания '__' перед именем атрибута, это делает атрибут недоступным вне класса. Он становится закрытым атрибутом , что означает, что вы не можете читать и записывать эти атрибуты, кроме как внутри класса. Обычно используется разработчиком модуля.
    • Если вы не используете подчеркивание перед атрибутом, это общедоступный атрибут , доступ к которому можно получить внутри или вне класса.
    класс Квартира:
        защита __init__(сам):
            self.type = "премиум"
            self.__bhk = "3 BHK"
    flat_1 = Квартира()
    квартира_1.тип
    премия
    flat_1.__bhk
    AttributeError: объект «Плоский» не имеет атрибута «__bhk»
     

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

    Добытчики и сеттеры

    Они используются для получения и обновления значения переменной. Сеттер — это метод, который обновляет значение переменной. Getter — это метод, который считывает значение переменной. Давайте узнаем это на примерах.

    класс Транспортное средство:
        def __init__(я,имя_водителя,фамилия_водителя):
            self.fdriver = имя_водителя
            self.ldriver = фамилия_водителя
            self.email = self.fdriver + '.' + self.ldriver + '@uber.com'
    veh_1 = Автомобиль ("Сэнди", "Стюарт")
    veh_1.fдрайвер
      Сэнди 
    veh_1.email
      'Сэнди.Стюарт@uber.com'
     
     

    Здесь мы обновляем имя водителя, но это не влияет на адрес электронной почты, который представляет собой комбинацию имени и фамилии.

    veh_1.fdriver = 'Том'
    veh_1.fдрайвер
      'Том' 
    veh_1.email
      'Сэнди.Стюарт@uber.com'
      

    Имя было изменено с Сэнди на Том, но адрес электронной почты остался прежним. Хорошо, возникает очевидный вопрос «как обновить адрес электронной почты?». С использованием @property декоратор мы можем изменить поведение электронной почты. email(self) — это метод, но он работает как обычное свойство. Этот специальный метод называется Getters and Setters

    .
    класс Транспортное средство:
        def __init__(я,имя_водителя,фамилия_водителя):
            self.fdriver = имя_водителя
            self.ldriver = фамилия_водителя
            
        @имущество
        адрес электронной почты (я):
            вернуть self.fdriver + '.' + self.ldriver + '@uber.com'
    veh_1 = Автомобиль ("Сэнди", "Стюарт")
    veh_1.fdriver = 'Том'
    veh_1.email
      '[email protected]' 
     

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

    класс Транспортное средство:
        def __init__(я,имя_водителя,фамилия_водителя):
            self.fdriver = имя_водителя
            self.ldriver = фамилия_водителя
            
        @имущество
        адрес электронной почты (я):
            вернуть self.fdriver + '.' + self.ldriver + '@uber.com'
        @email.setter
        адрес электронной почты (я, адрес):
            первый = адрес[:address. find('.')]
            последний = адрес[address.find('.')+1:address.find('@')]
            self.fdriver = первый
            self.ldriver = последний
    veh_1 = Автомобиль ("Сэнди", "Стюарт")
    veh_1.email = '[email protected]'
    veh_1.fдрайвер
      'глубокий' 
    veh_1.lдрайвер
      'бхалла' 
     

    Валидация

    В реальном мире геттеры и сеттеры в основном используются для включения логики проверки. В приведенном ниже примере мы создаем класс пожертвований с атрибутом суммы. Сумма должна находиться в диапазоне от 10 до 1 000 000. Если пользователь вводит меньше 10, оно должно быть установлено как 10. Точно так же, если пользователь пытается ввести значение больше 1 миллиона, оно должно быть ограничено только 1 миллионом.

    пожертвование класса:
        def __init__(я, количество):
            самостоятельная сумма = сумма
            
        @имущество
        Сумма защиты (я):
            вернуть себя.__сумма
        @amount.setter
        сумма защиты (я, сумма):
            если сумма 1000000:
                сам. __сумма = 1000000
            еще:
                self.__amount = количество
    благотворительность = пожертвование (5)
    благотворительность.сумма
      10 
     

    Как импортировать класс

    В этом разделе мы расскажем, как загрузить класс из другого файла или каталога.

    1. Сохраните следующий скрипт как Mymodule.py
    2. """
      Класс автомобиля
      """
      Кабина класса:
          
          #Инициализировать для первой итерации
          количество кабин = 0
          def __init__(я,водитель,км,оплата):
              self.driver = водитель
              автономный пробег = км
              селф.билл = платить
              Cab.numberofcabs = Cab.numberofcabs + 1
          #Возвращает среднюю цену за км
          def rateperkm(я):
              возврат self.bill/self.running
              
          #Возвращает количество запущенных кабин
          @классметод
          определение noofcabs (cls):
              вернуть cls.numberofcabs
      если __name__ == "__main__":
          
          #Класс такси
          firstcab = Cab("Рамеш", 80, 1200)
          Атрибут #driver в классе Cab
          печать (firstcab. driver)
          
          #метод класса
          печать (Cab.noofcabs())
       
    3. В приведенном ниже коде укажите каталог, в котором хранится файл Mymodule.py
    4. импорт ОС
      os.chdir("C:/Пользователи/DELL/Рабочий стол/")
      импортировать мой модуль
       
    5. Создайте объект или запустите методы, как обычно. Обязательно добавьте имя модуля в качестве префикса перед использованием класса и метода класса
    6. .
      #Класс кабины в Mymodule.py
      firstcab = Mymodule.Cab("Рамеш", 80, 1200)
      Атрибут #driver в классе кабины
      firstcab.водитель
      Метод экземпляра #rateperkm в Mymodule2.py
      firstcab.rateperkm()
      Метод класса #noofcabs в Mymodule2.py
      Мой модуль.Cab.noofcabs()
       
      Чтобы избежать написания имени модуля для доступа к классу, вы можете использовать «из», который загружает модуль в текущее пространство имен.
      из импорта Mymodule *
      firstcab = Cab("Сэнди", 80, ['Дели', 'Нойда'], 1200, 3)
       

    Что такое __name__ == "__main__"?

    Любой код, находящийся внутри , если __name__ == '__main__': , будет выполняться, когда вы запускаете файл . py напрямую (из терминала).

    Если вы импортируете модуль , импортируйте Mymodule , код внутри if __name__ == '__main__': не будет запущен.

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

    если __name__ == '__main__':
        print('Первый результат')
    еще:
        print('Второй результат')
     

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

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

    Упражнение

    Создайте класс Rectangle с атрибутами длины и ширины. Создайте 2 метода для вычисления площади прямоугольника и периметра прямоугольника. Площадь рассчитывается путем умножения длины на ширину. Периметр в 2 раза больше (длина+ширина). Решите и опубликуйте свое решение в поле для комментариев.

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

    изучать объектно-ориентированное программирование в Python

    2 Оценки

    57 УРОКИ

    11 ЗАДЕЛЕНИЯ

    65 ПРЕИМЕРЫ

    69 Иллюстрации

    ПАТА ПИТАНА. язык для разработчиков и специалистов по данным. Расширьте свои возможности трудоустройства с помощью уроков, разработанных для практикующих разработчиков, таких как вы.

    5 модулей

    Путь исследования

    Обзор курса

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

    Быстрее, чем видео

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

    Настройка не требуется

    Немедленно приступайте к обучению, вместо того чтобы возиться с SDK и IDE. Это все в облаке.

    Прогресс, который вы можете показать

    Встроенные тесты позволяют проверить свои навыки. Сертификаты об окончании позволяют их показать.

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

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

    Быстрее, чем видео

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

    Настройка не требуется

    Немедленно приступайте к обучению, вместо того чтобы возиться с SDK и IDE. Это все в облаке.

    Прогресс, который вы можете показать

    Встроенные тесты позволяют проверить свои навыки. Сертификаты об окончании позволяют их показать.

    Содержание курса

    1. Введение в объектно-ориентированное программирование

    Краткое введение в современные объектно-ориентированные языки

    2. Классы и объекты

    Введение в объекты и классы Методы и статические методыМодификаторы доступаБыстрый тест!Задание 1. Возведение чисел в квадрат и возврат их суммыОбзор решения 1. Возведение чисел в квадрат и возвращение их суммыЗадание 2. Расчет успеваемости учащегосяОбзор решения 2. Расчет успеваемости учащегосяЗадание 3. Реализация класса калькулятора Обзор решения 3. Реализация калькулятора Класс

    3. Сокрытие информации

    Что такое сокрытие информации?EncapsulationGetters и SettersПонимание инкапсуляции с использованием примеровБыстрый тест!Задание 1. Реализация класса Rectangle с помощью Encapsulation. Проверка решения. Реализация класса Rectangle с помощью Encapsulation. Задача 2. Реализация полного студенческого класса. Оценка курса

    Экзамен 1

    5. Наследование

    Что такое наследование?Синтаксис и терминологияСуперфункцияТипы наследованияПреимущества наследованияБыстрый тест!Задание 1. Внедрение банковского счета. Обзор решения. Внедрение банковского счета. банковский счет

    6.

    Оставить комментарий

    Добавить комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *

    © 2019 Штирлиц Сеть печатных салонов в Перми

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