Абстракция, инкапсуляция и полиморфизм — это ключевые принципы объектно-ориентированного программирования (ООП). В Python их можно реализовать следующим образом:
Абстракция:
Абстракция заключается в представлении пользователю только необходимой информации об объекте, скрывая детали реализации. В Python абстракция достигается несколькими способами:
Пример абстрактного класса:
 from abc import ABC, abstractmethod
 class Shape(ABC):
  @abstractmethod
  def area(self):
   pass
 class Circle(Shape):
  def __init__(self, radius):
   self.radius = radius
  def area(self):
   return 3.14159 * self.radius * self.radius
 class Square(Shape):
  def __init__(self, side):
   self.side = side
  def area(self):
   return self.side * self.side
 # shape = Shape()  # Ошибка: Нельзя создать экземпляр абстрактного класса
 circle = Circle(5)
 square = Square(4)
 print(f"Площадь круга: {circle.area()}")
 print(f"Площадь квадрата: {square.area()}")
  В этом примере `Shape` - абстрактный класс с абстрактным методом `area`. Классы `Circle` и `Square` наследуются от `Shape` и реализуют метод `area`, предоставляя конкретную реализацию для вычисления площади каждой фигуры.
Инкапсуляция:
Инкапсуляция заключается в сокрытии внутреннего состояния объекта и предоставлении доступа к нему только через методы. Это позволяет защитить данные от некорректного использования и упростить изменение реализации класса без влияния на остальной код.
Пример инкапсуляции:
 class BankAccount:
  def __init__(self, balance):
   self.__balance = balance  # Приватный атрибут
  def deposit(self, amount):
   if amount > 0:
    self.__balance += amount
   else:
    print("Сумма депозита должна быть положительной")
  def withdraw(self, amount):
   if 0 < amount <= self.__balance:
    self.__balance -= amount
   else:
    print("Недостаточно средств или некорректная сумма для снятия")
  def get_balance(self):
   return self.__balance  # Getter
 account = BankAccount(1000)
 account.deposit(500)
 account.withdraw(200)
 print(f"Баланс: {account.get_balance()}")
 #print(account.__balance)  # Ошибка: AttributeError: 'BankAccount' object has no attribute '__balance'
 print(account._BankAccount__balance) # Можно, но не рекомендуется.  Наглядная иллюстрация name mangling
  В этом примере `__balance` — приватный атрибут. Доступ к нему извне класса осуществляется только через методы `deposit`, `withdraw` и `get_balance`, которые обеспечивают контроль над операциями с балансом.
Полиморфизм:
Полиморфизм означает "много форм". В контексте ООП, это означает, что объекты разных классов могут быть использованы единообразно, если они реализуют один и тот же интерфейс (набор методов).
Пример полиморфизма:
 class Dog:
  def speak(self):
   return "Woof!"
 class Cat:
  def speak(self):
   return "Meow!"
 def animal_sound(animal):
  print(animal.speak())
 dog = Dog()
 cat = Cat()
 animal_sound(dog)
 animal_sound(cat)
  Функция `animal_sound` принимает объект типа `animal` (любого класса) и вызывает метод `speak`. Неважно, является ли объект собакой или кошкой, главное, чтобы у него был метод `speak`. Это и есть полиморфизм.
Взаимосвязь:
Эти три принципа тесно связаны между собой. Абстракция определяет общий интерфейс, инкапсуляция скрывает детали реализации, а полиморфизм позволяет использовать объекты разных классов через общий интерфейс.