Python Lab

ООП в Python для начинающих: классы, наследование, магические методы

Объектно-ориентирова��ное программирование на Python с нуля: классы, инкапсуляция, наследование, полиморфизм.

20 декабря 2025 г.·12 мин чтения
ООПклассынаследованиеpython basics

Что такое класс?

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

class Dog:
    # Конструктор — вызывается при создании объекта
    def __init__(self, name, breed):
        self.name = name    # атрибут экземпляра
        self.breed = breed

    # Метод экземпляра
    def bark(self):
        print(f"{self.name}: Гав!")

# Создание объектов
rex = Dog("Rex", "Лабрадор")
buddy = Dog("Buddy", "Пудель")

rex.bark()      # Rex: Гав!
buddy.bark()    # Buddy: Гав!
print(rex.name) # Rex

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

class BankAccount:
    def __init__(self, owner, balance=0):
        self.owner = owner
        self._balance = balance       # "защищённый" (соглашение)
        self.__secret = "тайна"       # "приватный" (name mangling)

    @property
    def balance(self):
        return self._balance

    def deposit(self, amount):
        if amount <= 0:
            raise ValueError("Сумма должна быть положительной")
        self._balance += amount

    def withdraw(self, amount):
        if amount > self._balance:
            raise ValueError("Недостаточно средств")
        self._balance -= amount

acc = BankAccount("Alice", 1000)
acc.deposit(500)
print(acc.balance)  # 1500

# acc._balance = -9999  # можно, но не нужно
# acc.__secret             # AttributeError

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

class Animal:
    def __init__(self, name):
        self.name = name

    def speak(self):
        raise NotImplementedError("Подкласс должен реализовать метод speak()")

    def __str__(self):
        return f"{self.__class__.__name__}({self.name})"


class Dog(Animal):
    def speak(self):
        return f"{self.name}: Гав!"


class Cat(Animal):
    def speak(self):
        return f"{self.name}: Мяу!"


class Duck(Animal):
    def speak(self):
        return f"{self.name}: Кря!"


animals = [Dog("Rex"), Cat("Whiskers"), Duck("Donald")]
for animal in animals:
    print(animal.speak())
# Rex: Гав!
# Whiskers: Мяу!
# Donald: Кря!

super() — вызов родительского класса

class Vehicle:
    def __init__(self, brand, speed):
        self.brand = brand
        self.speed = speed

    def info(self):
        return f"{self.brand}, {self.speed} км/ч"


class ElectricCar(Vehicle):
    def __init__(self, brand, speed, battery):
        super().__init__(brand, speed)     # вызов родительского __init__
        self.battery = battery

    def info(self):
        base = super().info()
        return f"{base}, батарея: {self.battery} кВтч"


tesla = ElectricCar("Tesla", 250, 100)
print(tesla.info())  # Tesla, 250 км/ч, батарея: 100 кВтч

Магические методы (dunder methods)

class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __repr__(self):
        return f"Vector({self.x}, {self.y})"

    def __str__(self):
        return f"({self.x}, {self.y})"

    def __add__(self, other):
        return Vector(self.x + other.x, self.y + other.y)

    def __mul__(self, scalar):
        return Vector(self.x * scalar, self.y * scalar)

    def __len__(self):
        return 2

    def __eq__(self, other):
        return self.x == other.x and self.y == other.y

    def __abs__(self):
        return (self.x**2 + self.y**2) ** 0.5


v1 = Vector(1, 2)
v2 = Vector(3, 4)

print(v1 + v2)      # (4, 6)
print(v1 * 3)       # (3, 6)
print(len(v1))      # 2
print(abs(v2))      # 5.0
print(v1 == Vector(1, 2))  # True

@classmethod и @staticmethod

class Date:
    def __init__(self, year, month, day):
        self.year = year
        self.month = month
        self.day = day

    @classmethod
    def from_string(cls, date_string):
        """Альтернативный конструктор"""
        year, month, day = map(int, date_string.split("-"))
        return cls(year, month, day)

    @staticmethod
    def is_valid(year, month, day):
        """Утилита, не требует доступа к экземпляру"""
        return 1 <= month <= 12 and 1 <= day <= 31

    def __str__(self):
        return f"{self.year:04d}-{self.month:02d}-{self.day:02d}"


d = Date.from_string("2025-12-01")
print(d)                            # 2025-12-01
print(Date.is_valid(2025, 2, 30))   # False

@dataclass — современный подход

from dataclasses import dataclass, field
import math

@dataclass
class Point:
    x: float
    y: float

    def distance_to(self, other: "Point") -> float:
        return math.sqrt((self.x - other.x)**2 + (self.y - other.y)**2)


@dataclass
class Circle:
    center: Point
    radius: float

    @property
    def area(self) -> float:
        return math.pi * self.radius ** 2


p1 = Point(0, 0)
p2 = Point(3, 4)
print(p1.distance_to(p2))    # 5.0

c = Circle(Point(0, 0), 5)
print(f"{c.area:.2f}")        # 78.54

Абстрактные классы

from abc import ABC, abstractmethod

class Shape(ABC):
    @abstractmethod
    def area(self) -> float:
        pass

    @abstractmethod
    def perimeter(self) -> float:
        pass

    def describe(self):
        return f"Площадь: {self.area():.2f}, Периметр: {self.perimeter():.2f}"


class Rectangle(Shape):
    def __init__(self, width, height):
        self.width = width
        self.height = height

    def area(self): return self.width * self.height
    def perimeter(self): return 2 * (self.width + self.height)


class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius

    def area(self): return 3.14159 * self.radius ** 2
    def perimeter(self): return 2 * 3.14159 * self.radius


shapes = [Rectangle(4, 5), Circle(3)]
for s in shapes:
    print(s.describe())

Принципы SOLID кратко

ПринципСуть
S Single ResponsibilityКласс отвечает за одну вещь
O Open/ClosedОткрыт для расширения, закрыт для изменений
L Liskov SubstitutionПодкласс можно использовать вместо родительского
I Interface SegregationМаленькие интерфейсы лучше одного большого
D Dependency InversionЗависимость от абстракций, не от реализаций

Практикуйте ООП в разделе «Классы» тренажёра — 30 задач от базовых __init__ до дескрипторов и метаклассов!

Хочешь закрепить знания?

Попробуй решить задачи на Python в интерактивном тренажёре

К задачам