Featured image of post Py09. Основы ООП в Python

Py09. Основы ООП в Python

Введение в ООП, классы и объекты, наследование, полиморфизм и инкапсуляция

Введение в ООП

Что такое ООП

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

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

Принципы ООП

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

Еще два принципа ООП, которые не были упомянуты ранее: абстракция и композиция.

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

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

Преимущества и недостатки ООП

✅ Преимущества ООП

  • Более структурированный и модульный код
  • Повторное использование кода
  • Улучшенная поддерживаемость

❎ Недостатки ООП

  • Высокий уровень абстракции может усложнить понимание кода
  • Добавление новых функций может потребовать много времени и усилий

Другие подходы к программированию

В дополнение к ООП, существуют и другие подходы к программированию:

  • Процедурное программирование - это подход, который фокусируется на выполняемых процедурах и функциях.
  • Функциональное программирование - это подход, который фокусируется на использовании функций.
  • Логическое программирование - это подход, который фокусируется на использовании формальной логики для решения задач.

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

Парадигма программирования Общее использование Основные характеристики Преимущества Недостатки
Объектно-ориентированное программирование Широко используется в разработке программного обеспечения Использует объекты для представления данных и поведения Инкапсуляция, Наследование, Полиморфизм, Абстракция, Композиция Высокий уровень абстракции может усложнить понимание кода
Процедурное программирование Используется для крупномасштабных проектов, где важна организация кода Использует процедуры и функции для представления поведения Модульность, Повторное использование, Легкость поддержки Может быть менее эффективным, чем другие парадигмы
Функциональное программирование Используется для математических и научных вычислений Сфокусирован на вычислении функций и избегает изменения состояния и изменяемых данных Неизменяемость, Референциальная прозрачность, Функции высшего порядка Может быть сложным для изучения и понимания
Логическое программирование Используется для искусственного интеллекта и систем на основе знаний Использует формальную логику для представления и решения задач Декларативность, Легкость отладки, Может обрабатывать сложные задачи Ограниченная поддержка для нелогических задач, Может быть менее эффективным, чем другие парадигмы

Базовые определения

Класс - это шаблон для создания объектов, а объект - это экземпляр класса.

Методы - это функции, принадлежащие определенному классу.

Атрибуты - это переменные, принадлежащие определенному объекту. Переменные - это временные хранилища для значений.

ООП в python

Как создать класс в Python

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

Пример класса:

1
2
3
4
5
6
7
8
9
class MyClass:
    def __init__(self, name):
        self.name = name

    def say_hello(self):
        print(f"Hello, {self.name}!")

my_object = MyClass("World")
my_object.say_hello() # Output: Hello, World!

Другие примеры

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
class Car:
    def __init__(self, color, model):
        self.color = color
        self.model = model
        self.speed = 0  # начальная скорость
        self.position = 0  # начальная позиция

    def go(self, speed):
        self.speed = speed  # задать скорость

    def get_position(self):
        self.position += self.speed  # увеличить позицию на текущую скорость
        return self.position  # вернуть позицию
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
class Robot:
    def __init__(self, name):
        self.name = name
        self.memory = []  # пустой список для запоминания текста

    def say(self, text):
        print(text)

    def remember(self, text):
        self.memory.append(text)  # добавить текст в список запомненного

    def retell(self):
        print(' '.join(self.memory))  # соединить все тексты из списка в одну строку и вывести ее
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
class Student:
    def __init__(self, name, grade):
        self.name = name
        self.grade = grade

class School:
    def __init__(self, name):
        self.name = name
        self.students = []  # пустой список учеников

    def add_student(self, student):
        self.students.append(student)  # добавить ученика в список
1
2
3
4
5
6
class Person:
    def __init__(self, name):
        self.name = name

    def say_hello(self):
        print('Hello, my name is', self.name)

Классы Car, Robot, School и Person являются примерами создания классов в Python. В блоке кода, представляющем каждый класс, описываются его атрибуты и методы.

Car - класс для создания объектов машин, у которых есть цвет, модель, скорость и позиция. Метод go задает скорость машины, а метод get_position возвращает текущую позицию машины.

Robot - класс для создания объектов роботов, у которых есть имя и список запомненных текстов. Метод say выводит заданный текст, метод remember добавляет текст в список запомненных, а метод retell выводит все запомненные тексты в одну строку.

School - класс для создания объектов школ, у которых есть название и список учеников. Метод add_student добавляет ученика в список.

Person - класс для создания объектов людей, у которых есть имя. Метод say_hello выводит приветствие с именем объекта.

Пример использования этих классов:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# Создаем объекты классов
car = Car('Red', 'Tesla')
robot = Robot('R2D2')
school = School('School #1')
person = Person('John')

# Используем методы объектов
car.go(60)
print(car.get_position())

robot.say('Hello, World!')
robot.remember('Buy milk')
robot.remember('Feed the cat')
robot.retell()

student1 = Student('Alice', 9)
student2 = Student('Bob', 10)

school.add_student(student1)
school.add_student(student2)

print(school.students)

person.say_hello()

Результат выполнения кода:

1
2
3
4
5
60
Hello, World!
Buy milk Feed the cat
[<__main__.Student object at 0x7f8c3f12de10>, <__main__.Student object at 0x7f8c3f12df98>]
Hello, my name is John

В этом примере мы создали объекты классов Car, Robot, School и Person, и использовали их методы для задания скорости машины, запоминания текста роботом, добавления учеников в школу и приветствия человека.

Таблица всех dunder методов и их описания

В ООП классы используются для создания объектов, которые могут быть использованы в программе. Однако, что делать, если мы хотим, чтобы объекты могли складываться, вычитаться или выполнять код при вызове? В Python для этого существуют специальные методы, называемые “dunder methods”, которые позволяют определить поведение объектов при выполнении различных операций. Например, метод add позволяет определить, как складывать два объекта, а метод call позволяет определить, как выполнять код при вызове объекта. Решение этих задач и многое другое будет рассмотрено в данном курсе. Dunder-методы это методы, которые начинаются и заканчиваются на два символа подчеркивания. Они используются для реализации различных магических методов.

Метод Описание
__init__(self, ...) Инициализация объекта
__str__(self) Возвращает строковое представление объекта
__repr__(self) Возвращает строковое представление объекта для отладки
__len__(self) Возвращает длину объекта
__add__(self, other) Возвращает результат сложения двух объектов
__sub__(self, other) Возвращает результат вычитания двух объектов
__mul__(self, other) Возвращает результат умножения двух объектов
__truediv__(self, other) Возвращает результат деления двух объектов
__floordiv__(self, other) Возвращает результат целочисленного деления двух объектов
__mod__(self, other) Возвращает результат операции модуля двух объектов
__pow__(self, other) Возвращает результат возведения одного объекта в степень другого
__lt__(self, other) Возвращает True, если текущий объект меньше, чем объект other
__le__(self, other) Возвращает True, если текущий объект меньше или равен объекту other
__eq__(self, other) Возвращает True, если текущий объект равен объекту other
__ne__(self, other) Возвращает True, если текущий объект не равен объекту other
__gt__(self, other) Возвращает True, если текущий объект больше, чем объект other
__ge__(self, other) Возвращает True, если текущий объект больше или равен объекту other
__hash__(self) Возвращает хеш-значение объекта
__bool__(self) Возвращает False, если объект пустой, и True, если нет
__getattr__(self, name) Вызывается при обращении к несуществующему атрибуту объекта
__setattr__(self, name, value) Вызывается при установке значения атрибута объекта
__delattr__(self, name) Вызывается при удалении атрибута объекта
__call__(self, ...) Вызывается при вызове объекта как функции
__enter__(self) Вызывается при входе в блок контекстного менеджера
__exit__(self, exc_type, exc_val, exc_tb) Вызывается при выходе из блока контекстного менеджера
__iter__(self) Возвращает итератор для объекта
__next__(self) Возвращает следующий элемент итератора
__getitem__(self, key) Возвращает элемент по индексу или ключу
__setitem__(self, key, value) Устанавливает значение элемента по индексу или ключу
__delitem__(self, key) Удаляет элемент по индексу или ключу
__contains__(self, item) Возвращает True, если объект содержит элемент item
__index__(self) Возвращает целочисленное представление объекта
__reversed__(self) Возвращает обратный итератор для объекта
__enter__(self) Вызывается при входе в блок контекстного менеджера
__exit__(self, exc_type, exc_val, exc_tb) Вызывается при выходе из блока контекстного менеджера
__dir__(self) Возвращает список атрибутов объекта
__format__(self, format_spec) Форматирует объект с помощью указанной спецификации формата
__bytes__(self) Возвращает байтовое представление объекта
__class__(self) Возвращает ссылку на класс объекта
__instancecheck__(self, instance) Возвращает True, если объект является экземпляром указанного класса
__subclasscheck__(self, subclass) Возвращает True, если класс является наследником указанного класса
__getattribute__(self, name) Вызывается при обращении к атрибуту объекта
__setattr__(self, name, value) Вызывается при установке значения атрибута объекта
__delattr__(self, name) Вызывается при удалении атрибута объекта
__dir__(self) Возвращает список атрибутов объекта
__enter__(self) Вызывается при входе в блок контекстного менеджера
__exit__(self, exc_type, exc_val, exc_tb) Вызывается при выходе из блока контекстного менеджера
__get__(self, instance, owner) Возвращает значение атрибута
__set__(self, instance, value) Устанавливает значение атрибута
__delete__(self, instance) Удаляет значение атрибута

В чем разница между init и new? __init__ - это магический метод, который вызывается при создании нового объекта класса. __new__ - это метод, который создает новый объект класса.

Self

self - это параметр метода, который ссылается на экземпляр класса, для которого вызывается метод. Он используется для доступа к атрибутам и методам объекта. Когда мы вызываем метод на объекте, Python автоматически передает этот объект в качестве первого параметра метода, используя параметр self. Это позволяет нам оперировать данными конкретного объекта и изменять их внутри методов. Без параметра self мы бы не имели доступа к атрибутам и методам объекта и не могли бы изменять их значения.

self - это ссылка на текущий объект. self используется для доступа к атрибутам и методам объекта.

Декоратор @property

@property - это декоратор, который позволяет использовать метод как атрибут.

Для использования декоратора @property необходимо определить метод с этим декоратором.

Пример класса с использованием декоратора @property:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
class Rectangle:
    def __init__(self, length, width):
        self.length = length
        self.width = width

    @property
    def area(self):
        return self.length * self.width

    @property
    def perimeter(self):
        return 2 * (self.length + self.width)

Здесь класс Rectangle имеет два атрибута - length и width, которые задают длину и ширину прямоугольника соответственно. Декоратор @property используется для создания атрибутов area и perimeter, которые вычисляют площадь и периметр прямоугольника соответственно.

Пример использования класса:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
>>> r = Rectangle(4, 5)
>>> r.length
4
>>> r.width
5
>>> r.area
20
>>> r.perimeter
18
>>> r.length = 6
>>> r.width = 7
>>> r.area
42
>>> r.perimeter
26

Здесь мы создаем экземпляр класса Rectangle с длиной 4 и шириной 5, и затем используем атрибуты length, width, area и perimeter для получения соответствующих значений. Затем мы меняем значения атрибутов length и width, и снова используем атрибуты area и perimeter, чтобы получить новые значения.

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

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

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Animal:
    def __init__(self, name, sound):
        self.name = name
        self.sound = sound

    def make_sound(self):
        print(f'{self.name} издает звук "{self.sound}"')

class Cat(Animal):
    def __init__(self, name):
        super().__init__(name, "Мяу")

    def purr(self):
        print(f'{self.name} мурлычет')

class Dog(Animal):
    def __init__(self, name):
        super().__init__(name, "Гав")

    def wag_tail(self):
        print(f'{self.name} виляет хвостом')

cat = Cat("Барсик")
cat.make_sound()
cat.purr()

dog = Dog("Шарик")
dog.make_sound()
dog.wag_tail()

В этом примере мы определяем базовый класс Animal, который имеет два атрибута - name и sound - и метод make_sound(), который выводит сообщение со звуком, издаваемым животным.

Затем мы определяем два класса, Cat и Dog, которые наследуются от Animal. Каждый из этих классов переопределяет метод __init__(), чтобы задать соответствующий звук, и добавляет свой собственный метод - purr() для Cat и wag_tail() для Dog.

Затем мы создаем экземпляры классов Cat и Dog, и вызываем методы make_sound(), purr() и wag_tail() для каждого из них. Это демонстрирует, как наследование позволяет создавать новые классы на основе существующих и добавлять им собственные методы и атрибуты.

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

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

  • Создавайте классы, которые отвечают только за одну задачу, и следуйте принципу единственной ответственности.
  • Используйте наследование, чтобы избежать дублирования кода и упростить его поддержку.
  • Используйте полиморфизм, чтобы обеспечить гибкость кода и упростить его использование.
  • Используйте инкапсуляцию, чтобы скрыть детали реализации и обеспечить безопасность кода.
  • Помните, что классы должны моделировать реальные объекты и процессы, а не только выполнять задачи.
  • Документируйте каждый класс и его методы, чтобы облегчить его использование другими разработчиками.

Частые ошибки при создании классов

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

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

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

Особенности ООП в Python

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

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

Еще одной особенностью ООП в Python является наличие магических методов, которые позволяют определять поведение объектов в различных ситуациях. Например, метод __str__ определяет строковое представление объекта, а метод __len__ определяет длину объекта. Магические методы позволяют создавать более гибкие и мощные объекты, но их неправильное использование может привести к сложностям в понимании кода.

В Python также есть возможность использовать декораторы, которые позволяют модифицировать поведение методов и классов. Например, декоратор @property позволяет использовать метод как атрибут, а декоратор @staticmethod позволяет определить статический метод, который не имеет доступа к атрибутам и методам объекта.

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

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

Примеры использования ООП

Примеры использования ООП в Python

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

Итоги

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

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

Спасибо за внимание и удачи в вашем путешествии в мир программирования!

comments powered by Disqus
Сделано с 💖
Создано при помощи Hugo
Тема Stack, дизайн Jimmy