Что такое классы в Python
Класс — это шаблон, по которому создаются объекты: в нём записано, какие данные хранит каждый объект и какие действия с ними можно выполнять. Объявляют его словом class.
Вы уже пользовались классами, даже если не знали этого. Строка, список и число в Python — тоже объекты встроенных классов. Проверьте: print(type(5)) выведет <class 'int'>, а type("кот") — <class 'str'>. Когда вы пишете slova.append("мяч") или imya.upper(), вы вызываете метод объекта — действие, которое этот объект умеет выполнять. Свой класс позволяет создать такой же тип с нуля: «Питомец», «Игрок», «Монстр», «Банковская копилка».
В редакторе выше уже есть класс Pet. Нажмите «▶ Запустить»: два питомца, Барсик и Рекс, живут независимо, и у каждого свой уровень голода. Попробуйте добавить третьего — достаточно одной строки. В документации Python классам посвящена отдельная глава, и пример с собакой там очень похож на наш.
Класс и объект: чертёж и вещь
Если класс — это чертёж велосипеда, то объект — конкретный велосипед, собранный по нему. По 1 чертежу можно собрать сколько угодно велосипедов, и у каждого будет свой цвет и пробег.
class Cat:
pass
murka = Cat()
vaska = Cat()
print(murka == vaska)
False
Здесь Cat — пустой класс: слово pass означает «пока ничего». Строка Cat() со скобками создаёт новый объект, или, как говорят, экземпляр класса. Мы создали два объекта, и Python считает их разными, хотя внутри они одинаково пусты. Имя класса по правилам PEP 8 пишут с заглавной буквы, а если в нём несколько слов — каждое с заглавной: GamePlayer. Так класс легко отличить от переменной или функции, у которых имена строчными буквами[1].
Конструктор __init__ и атрибуты
Метод __init__ — это особая функция внутри класса, которую Python вызывает автоматически при создании объекта. В ней объекту выдают стартовые свойства — атрибуты.
class Pet:
def __init__(self, name, kind):
self.name = name
self.kind = kind
self.hunger = 5
barsik = Pet("Барсик", "Кот")
print(barsik.name, barsik.hunger)
Барсик 5
Когда мы пишем Pet("Барсик", "Кот"), Python создаёт пустой объект и передаёт его в __init__ вместе с аргументами. Строки self.name = name записывают значения внутрь объекта. Атрибут hunger не передаётся снаружи: у каждого нового питомца он сразу равен 5. Обратиться к атрибуту можно через точку: barsik.name. Возвращать значение из __init__ не нужно: его единственная задача — заполнить атрибуты нового объекта. Имя метода пишется с двумя подчёркиваниями с каждой стороны; с одним подчёркиванием Python не узнает конструктор и при создании объекта сообщит TypeError: Pet() takes no arguments.
Что такое self и зачем он нужен
self — это ссылка на тот самый объект, с которым сейчас работает метод. Python подставляет её автоматически первым аргументом, поэтому при вызове barsik.feed() скобки пустые.
Представьте, что у вас два питомца. Метод feed один на весь класс, но кормить нужно конкретного зверя. Когда вы пишете barsik.feed(), Python на самом деле выполняет Pet.feed(barsik): внутри метода self — это Барсик. Для rex.feed() тем же self окажется Рекс. Так один код работает с любым объектом, не путая их данные.
Слово self — не ключевое слово, а договорённость: технически параметр можно назвать иначе, но так никто не делает, и в официальной документации Python везде используется именно это имя[2]. Самая частая ошибка — забыть self в списке параметров метода. Тогда при вызове Python сообщит TypeError: метод получил на один аргумент больше, чем ожидал.
Методы: что объект умеет делать
Метод — это функция, объявленная внутри класса, которая работает с данными объекта через self. Вызывают его через точку: объект.метод().
class Pet:
def __init__(self, name):
self.name = name
self.hunger = 5
def feed(self):
self.hunger = max(0, self.hunger - 3)
def play(self):
self.hunger = self.hunger + 2
rex = Pet("Рекс")
rex.play()
rex.play()
rex.feed()
print(rex.name, rex.hunger)
Рекс 6
Голод был 5, две игры прибавили по 2, кормление отняло 3: 5 + 2 + 2 − 3 = 6. Функция max(0, ...) не даёт голоду уйти ниже нуля. Обратите внимание: методы меняют атрибуты объекта, и эти изменения сохраняются между вызовами. Обычная функция так не умеет: её локальные переменные пропадают после возврата, и сохранить в них что-то до следующего вызова не получится. Руководство PEP 8 советует отделять методы класса друг от друга одной пустой строкой — так их легче различать при чтении. В этом главное удобство класса — данные и действия над ними живут вместе. Если тема функций пока неуверенная, начните со статьи про функции в Python: методы устроены так же, только с self.
Пример «Питомец» целиком
Программа в редакторе — это полный класс «Питомец» с 3 методами: накормить, поиграть и показать информацию. Разберём, что происходит при запуске.
- Объявление класса. Python запоминает чертёж, но ничего не выводит.
- Создание двух объектов. Для Барсика и Рекса вызывается
__init__, у обоих голод 5. - Барсик играет. Его голод становится 7, у Рекса остаётся 5.
- Барсик ест. Голод падает до 4.
- Вывод информации. Рекс — голод 5, Барсик — голод 4.
Попробуйте расширить класс сами. Добавьте атрибут mood («настроение») и метод sleep, который уменьшает голод на 1, но поднимает настроение. Или заставьте питомца «грустить», если голод больше 8: для этого в метод info понадобится условие if. Такие маленькие улучшения — лучший способ понять, как устроен класс.
Классы в Python и спрайты Scratch
Спрайт в Scratch — это почти объект: у него есть свои переменные «для этого спрайта», свои скрипты и свои костюмы. Классы в Python делают ту же идею явной и гибкой.
Создатели Scratch из MIT Media Lab описывали спрайты как самостоятельных персонажей со своим состоянием и поведением[3]. Если ребёнок делал игру со снежинками-клонами, он уже встречал главную мысль: один набор скриптов, много копий, у каждой свои координаты. В Python роль «оригинала» играет класс, а клонов — объекты. Разница в том, что в Python класс пишется заранее, а объектов можно создать сотни одной строкой в цикле и хранить их в списке.
| Scratch | Python |
| спрайт-оригинал со скриптами | класс с методами |
| клон | объект, созданный вызовом Pet(...) |
| переменная «только для этого спрайта» | атрибут self.hunger |
| блок «когда я начинаю как клон» | метод __init__ |
Когда класс не нужен
Класс не нужен, если программа короткая и в ней нет нескольких похожих «существ» со своим состоянием. В этих 4 случаях проще обойтись функциями и переменными.
- Программа на 10–20 строк. Ввод, расчёт и вывод не требуют чертежей.
- Задание 16 ОГЭ. Там нужна короткая программа с вводом и циклом, классы её только удлинят.
- Одна функция без состояния. Перевод градусов или подсчёт 1 суммы проще оставить обычной функцией.
- Первые 2–3 месяца изучения Python. Сначала нужны уверенные циклы, списки и функции, иначе self и атрибуты превратятся в заучивание.
Миф: «без классов программа на Python ненастоящая». Это не подтверждается: множество полезных программ обходится функциями, а руководство по стилю и документация Python не требуют оборачивать код в классы.
Миф: «классы — это тема для студентов, школьнику их не понять». Такого возрастного барьера не существует: если ребёнок понимает функции и списки, пример с питомцем обычно становится ясен за одно занятие.
Чего делать нельзя
Нельзя забывать self — это ошибка номер один во всех первых программах с классами. Вот и другие типичные промахи.
- Нельзя пропускать self первым параметром метода — будет TypeError при вызове.
- Не стоит писать
name = nameвместоself.name = name: значение не сохранится в объекте. - Не следует путать _init_ и __init__: нужно по два подчёркивания с каждой стороны.
- Не стоит вызывать метод без скобок:
rex.feedничего не сделает. - Нельзя обращаться к атрибуту, который не создан в __init__ или методе, — будет AttributeError.
- Не стоит делать класс ради одной функции — код станет длиннее без пользы.
Если Python пишет, что у объекта нет нужного атрибута, загляните в разбор ошибки AttributeError. В школьной программе базового уровня классов нет: по федеральной образовательной программе в старших классах основной школы изучают массивы и вспомогательные алгоритмы[4]. Классы — следующий шаг для тех, кто пишет свои проекты, например игры; про путь от первых игр к серьёзным рассказано в статье если ребёнок хочет делать игры.
Источники
[1] van Rossum G., Warsaw B., Coghlan N. PEP 8 — Style Guide for Python Code. Python Software Foundation, 2001.
[2] The Python Tutorial (официальная документация Python 3). Python Software Foundation.
[3] Maloney J., Resnick M., Rusk N., Silverman B., Eastmond E. The Scratch Programming Language and Environment // ACM Transactions on Computing Education. 2010. Vol. 10, № 4. Article 16.
[4] Приказ Минпросвещения России от 18.05.2023 № 370 «Об утверждении федеральной образовательной программы основного общего образования».
Вопросы и ответы
Чем атрибут отличается от переменной?
Атрибут — это переменная, которая принадлежит конкретному экземпляру и записывается через точку: rex.hunger. У каждого питомца своё значение.
Как вывести питомца через print красиво?
Добавьте в чертёж метод __str__, который возвращает строку. Тогда print(rex) покажет её вместо служебной записи с адресом в памяти.
Можно ли хранить питомцев в списке?
Да: zoo = [Pet("Барсик", "Кот"), Pet("Рекс", "Пёс")]. Потом циклом for p in zoo: p.feed() можно накормить всех сразу.
Что такое наследование?
Это создание нового чертежа на основе готового: class Dog(Pet): получает все методы Pet и может добавить свои, например bark. Тема следующего шага, после уверенной работы с основами.
С какого возраста изучать классы в Python?
Возраст здесь вторичен: важнее, чтобы ученик уверенно писал функции и работал со списками. Чаще всего к этому приходят в средней школе, после нескольких месяцев регулярной практики.
Работают ли такие программы в редакторе на сайте?
Да, интерпретатор на странице поддерживает собственные типы, методы и наследование. Ограничения касаются только внешних модулей.