Python · Синтаксис · Начальный уровень

Основы ООП

11 задач

Практические задания по основам ООП в Python: создание классов и объектов, атрибуты, методы, __init__, изменение состояния объекта и простое моделирование сущностей.

Классы и объекты — идея

#
Класс — это шаблон. Объект — это то, что вы строите по этому шаблону. Один и тот же класс может породить тысячи объектов, каждый со своими независимыми данными. До классов, если нужно было отслеживать несколько банковских счетов, пришлось бы использовать отдельные переменные для каждого баланса. С классом определяем структуру один раз и создаём сколько угодно экземпляров — каждый хранит своё собственное состояние. ```python class BankAccount: def __init__(self, balance): self.balance = balance acc1 = BankAccount(100) acc2 = BankAccount(500) print(acc1.balance) # 100 print(acc2.balance) # 500 ``` acc1 и acc2 — независимые объекты. Изменение acc1.balance не влияет на acc2. Классы объединяют две вещи: данные (атрибуты) и поведение (методы). Метод — это просто функция, определённая внутри класса. Именно такое объединение и является главной идеей объектно-ориентированного программирования: держите данные и код, работающий с ними, в одном месте.

__init__ и self

#
__init__ — специальный метод, который Python вызывает автоматически при создании нового объекта. Он настраивает начальное состояние экземпляра. ```python class Rectangle: def __init__(self, width, height): self.width = width self.height = height r = Rectangle(3, 4) print(r.width, r.height) # 3 4 ``` self — это ссылка на создаваемый объект. Когда вы пишете self.width = width, вы сохраняете значение на самом объекте, а не в локальной переменной, которая исчезнет после завершения __init__. Каждый атрибут, который должен помнить объект, должен быть присвоен через self. self всегда является первым параметром каждого метода, но вы никогда не передаёте его вручную. Python передаёт его автоматически. Когда вы вызываете r.area(), Python преобразует это в Rectangle.area(r) — r становится self внутри метода. ```python class Rectangle: def __init__(self, width, height): self.width = width self.height = height def area(self): return self.width * self.height r = Rectangle(3, 4) print(r.area()) # 12 ``` Метод использует self.width и self.height — значения, сохранённые во время __init__. Через self метод имеет доступ ко всему, что объект знает о себе.

Распространённые паттерны классов

#
Метод, изменяющий состояние объекта — ничего не возвращает, только изменяет атрибут: ```python class Counter: def __init__(self, value): self.value = value def increment(self): self.value += 1 c = Counter(0) c.increment() c.increment() print(c.value) # 2 ``` Метод, проверяющий условие и возвращающий булево значение: ```python class Person: def __init__(self, name, age): self.name = name self.age = age def is_adult(self): return self.age >= 18 ``` Метод, вычисляющий что-то на основе атрибутов и возвращающий значение: ```python class Temperature: def __init__(self, celsius): self.celsius = celsius def to_fahrenheit(self): return self.celsius * 9 / 5 + 32 ``` Метод, одновременно изменяющий состояние и проверяющий входные данные: ```python class BankAccount: def __init__(self, balance): self.balance = balance def deposit(self, amount): self.balance += amount ``` Паттерн всегда одинаков: обращаемся к нужному через self, вычисляем или изменяем, возвращаем только тогда, когда есть значимое значение для возврата.

Быстрый справочник: основы ООП

#
**Синтаксис класса** ```python class ИмяКласса: def __init__(self, параметр1, параметр2): self.атрибут1 = параметр1 # сохранить на объекте self.атрибут2 = параметр2 def метод(self): # self всегда первый return self.атрибут1 obj = ИмяКласса(знач1, знач2) # создать экземпляр obj.атрибут1 # прочитать атрибут obj.метод() # вызвать метод ``` **Правила `self`** | Правило | Почему | |---|---| | Каждый метод должен иметь `self` первым параметром | Python передаёт объект автоматически | | Используйте `self.имя` для хранения данных | просто `имя =` — это только локальная переменная | | Используйте `self.имя` для чтения в любом методе | все методы разделяют один объект | | Никогда не передавайте `self` вручную | `obj.метод()` а не `obj.метод(obj)` | **Типы методов** | Тип | Возвращает | Пример | |---|---|---| | Изменяет состояние | ничего (`None`) | `self.balance += amount` | | Проверяет условие | `bool` | `return self.age >= 18` | | Вычисляет значение | результат | `return self.w * self.h` | | Смешанный | зависит | валидация затем изменение | **Типичные ошибки** ```python # Забыть self. — создаётся локальная переменная которая исчезнет: def __init__(self, name): name = name # неверно — только локальная self.name = name # верно # Забыть self. в методе: def area(self): return width * height # NameError — должно быть self.width return self.width * self.height # верно # Пропустить self в сигнатуре: def area(): # неверно — Python передаёт obj первым аргументом def area(self): # верно ```
01

Класс User с именем.

#

Создайте класс User с атрибутом name . Создайте объект этого класса и выведите его имя.

class User:
    pass


u = User("Alex")
print(u.name)
Решение
class User:
    def __init__(self, name):
        self.name = name


u = User("Alex")
print(u.name)

# или можно создать метод, который возвращает имя
class User:
    def __init__(self, name):
        self.name = name

    def get_name(self):
        return self.name
02

Класс Car: бренд и год.

#

Создайте класс Car с атрибутами brand и year . Создайте объект и выведите строку: "Car: Toyota, 2020"

class Car:
    pass
Решение
class Car:
    def __init__(self, brand, year):
        self.brand = brand
        self.year = year


c = Car("Toyota", 2020)
print(f"Car: {c.brand}, {c.year}")

# или

class Car:
    def __init__(self, brand, year):
        self.brand = brand
        self.year = year
    def __str__(self):
        return f"Car: {self.brand}, {self.year}"


c = Car("Toyota", 2020)
print(c)
03

Счётчик с increment.

#

Создайте класс Counter с атрибутом value . Добавьте метод increment , который увеличивает значение на 1.

class Counter:
    pass


c = Counter(0)
c.increment()
print(c.value)
Решение
class Counter:
    def __init__(self, value):
        self.value = value

    def increment(self):
        self.value += 1


c = Counter(0)
c.increment()
print(c.value)

# или так можно: increment может возвращать новое значение
class Counter:
    def __init__(self):
        self.value = 0

    def increment(self):
        self.value += 1
        return self.value
04

Площадь прямоугольника.

#

Создайте класс Rectangle с атрибутами width и height . Добавьте метод area , который возвращает площадь.

class Rectangle:
    pass


r = Rectangle(3, 4)
print(r.area())
Решение
class Rectangle:
    def __init__(self, width, height):
        self.width = width
        self.height = height

    def area(self):
        return self.width * self.height


r = Rectangle(3, 4)
print(r.area())

# или так можно: площадь сначала сохранить в переменную
class Rectangle:
    def __init__(self, width, height):
        self.width = width
        self.height = height

    def area(self):
        result = self.width * self.height
        return result
05

Приветствие методом класса.

#

Создайте класс Greeting с методом say_hello , который возвращает строку "Hello!" .

class Greeting:
    pass


g = Greeting()
print(g.say_hello())
Решение
class Greeting:
    def say_hello(self):
        return "Hello!"


g = Greeting()
print(g.say_hello())
06

Проверка совершеннолетия.

#

Создайте класс Person с атрибутами name и age . Добавьте метод is_adult , который возвращает True , если возраст 18 и больше.

class Person:
    pass


p = Person("John", 20)
print(p.is_adult())
Решение
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def is_adult(self):
        return self.age >= 18


p = Person("John", 20)
print(p.is_adult())
07

Пополнение банковского счёта.

#

Создайте класс BankAccount с атрибутом balance . Добавьте метод deposit , который увеличивает баланс.

class BankAccount:
    pass


acc = BankAccount(100)
acc.deposit(50)
print(acc.balance)
Решение
class BankAccount:
    def __init__(self, balance):
        self.balance = balance

    def deposit(self, amount):
        self.balance += amount


acc = BankAccount(100)
acc.deposit(50)
print(acc.balance)

# или так можно: явно не позволять пополнять счёт отрицательной суммой
class BankAccount:
    def __init__(self, balance):
        self.balance = balance

    def deposit(self, amount):
        if amount > 0:
            self.balance += amount
08

Конвертация Celsius в Fahrenheit.

#

Создайте класс Temperature с атрибутом celsius . Добавьте метод to_fahrenheit , который возвращает температуру в градусах Фаренгейта. Формула такая: celsius * 9 / 5 + 32.

class Temperature:
    pass


t = Temperature(0)
print(t.to_fahrenheit())
Решение
class Temperature:
    def __init__(self, celsius):
        self.celsius = celsius

    def to_fahrenheit(self):
        return self.celsius * 9 / 5 + 32


t = Temperature(0)
print(t.to_fahrenheit())
09

Длина сообщения методом.

#

Создайте класс Message с атрибутом text . Добавьте метод length , который возвращает длину сообщения.

class Message:
    pass


m = Message("Hello world")
print(m.length())
Решение
class Message:
    def __init__(self, text):
        self.text = text

    def length(self):
        return len(self.text)


m = Message("Hello world")
print(m.length())
10

Таймер с добавлением секунд.

#

Создайте класс Timer с атрибутом seconds . Добавьте метод add_time , который увеличивает время на указанное количество секунд.

class Timer:
    pass


t = Timer(10)
t.add_time(5)
print(t.seconds)
Решение
class Timer:
    def __init__(self, seconds):
        self.seconds = seconds

    def add_time(self, extra):
        self.seconds += extra


t = Timer(10)
t.add_time(5)
print(t.seconds)
11

Класс Formatter для строк.

#

Напишите класс Formatter с атрибутом string у объекта. При создании экземпляра этого класса (объекта) туда передается строка, которая сохранятся в этот атрибут string у объекта. У этого класса должно быть несколько методов, которые должны возвращать измененный вариант этой строки, по их предназначению: - метод trim возвращает обрезанную до указанной длины строку в конце с "[...]" (длина этих добавленных символов должна быть учтена). - метод truncate возвращает обрезанную строку до указанной длины, но не "рвет слова", а обрезает ее по пробелу, но не длиннее указанной длины. Этого достаточно. ВНИМАНИЕ: - изначальная строка в self.string должна всегда оставаться изначальной. - никаких других атрибутов для результатов не создавать, только возвращать новые значения. Просто локальные переменные можно конечно. - можно создавать атрибуты для служебных данных, например для строки "[...]" Помните, что методы это просто особенные функции, куда в первый параметр self обязательно передается автоматически ссылка на сам объект, но все остальные правила в виде обычных локальных переменных и прочего как у обычных функций. То есть, не обязательно внутри метода всё навешивать на self.переменная, можно просто создавать локальные переменные как в обычных функциях.

class Formatter():
    def __init__(self, string):
        pass
    
    def trim(self, length):     
        pass
        
    def truncate(self, length):
        pass

    
x = Formatter("Эта строка для примера просто используется тут и не имеет другого смысла.")
print(x.trim(15))      # Эта строка[...]
print(x.truncate(15))  # Эта строка для
print(x.string)  # Изначальная строка

y = Formatter("Ура у меня получилось!.")
print(y.trim(8))      # Ура[...]
print(y.truncate(3))  # Ура
print(y.string)  # Изначальная строка
Решение
class Formatter():
    def __init__(self, string):
        self.string = string
        self.end = "[...]"
    
    def trim(self, length):     
        return self.string[: length - len(self.end)] + self.end
        
    def truncate(self, length):
        if self.string[length] == " ":
            return self.string[:length]
        
        return self.string[:length].rsplit(" ", 1)[0]
        
    
x = Formatter("Эта строка для примера просто используется тут и не имеет другого смысла.")
print(x.trim(15))      # Эта строка[...]
print(x.truncate(15))  # Эта строка для
print(x.string)  # Изначальная строка

y = Formatter("Ура у меня получилось!.")
print(y.trim(8))      # Ура[...]
print(y.truncate(3))  # Ура
print(y.string)  # Изначальная строка