Перейти к содержанию

232 уроков, 16 библиотек и челлендж «Что выведет код?» — бесплатно, код прямо в браузере

Начать обучение
Урок 4 из 20 Средний 30 мин 120 XP

Методы: обычные, classmethod и staticmethod

У методов Python три лика: обычный с self, classmethod с cls и staticmethod без ничего. Строим альтернативный конструктор from_string и расставляем границы.

Редакция Питоники

До сих пор все методы были «обычными»: первым параметром self, вызываются на объекте. Обычный метод работает с конкретным объектом — self его пропуск к атрибутам: корзина покупок помнит свои товары, и каждый вызов метода меняет именно свою корзину. Но у Python есть ещё два вида методов, которые закрывают другие задачи: конструирование объекта из нестандартных данных и утилиты, которым состояние не нужно вовсе. Если механика self ещё туманна, начните с урока про __init__ и self.

Обычный метод: self и состояние объекта

метод, который помнит объект
class Cart:
    def __init__(self):
        self.items = []

    def add(self, name):
        self.items.append(name)

    def total(self):
        return len(self.items)

cart = Cart()
cart.add("хлеб")
cart.add("молоко")
print(cart.total())
Вывод
2

@classmethod: метод класса и конструктор from_string

Декоратор @classmethod меняет правила: первый параметр метода — не объект, а сам класс, по традиции названный cls. Python передаёт его автоматически при вызове и через класс, и через экземпляр. classmethod нужен тогда, когда методу важен класс: чаще всего это альтернативный конструктор. Такой метод принимает данные в неудобном формате, разбирает их и возвращает новый экземпляр.

альтернативный конструктор из строки
class Meeting:
    def __init__(self, day, month, year):
        self.day = day
        self.month = month
        self.year = year

    @classmethod
    def from_string(cls, text):
        day, month, year = text.split(".")
        return cls(int(day), int(month), int(year))

    def describe(self):
        print(f"Встреча: {self.day}.{self.month}.{self.year}")

m = Meeting.from_string("15.10.2026")
m.describe()
Вывод
Встреча: 15.10.2026
ВидДекораторПервый аргументДля чего
обычный—self — экземплярработа с состоянием объекта
метод класса@classmethodcls — сам классальтернативные конструкторы, атрибуты класса
статический@staticmethodнетутилита, относящаяся к сущности класса

@staticmethod — метод без self и без cls: обычная функция, которой логично жить внутри класса, потому что она относится к его сущности. Проверка email до создания пользователя — классика: валидация нужна и до, и после создания объектов, а состояния она не трогает. Вызывается одинаково через класс и через экземпляр.

утилита внутри класса
class User:
    def __init__(self, email):
        self.email = email

    @staticmethod
    def is_valid_email(email):
        return "@" in email

print(User.is_valid_email("anna@example.com"))
print(User.is_valid_email("anna-example.com"))

u = User("boris@example.ru")
print(u.is_valid_email("test@mail.ru"))
Вывод
True
False
True

Три вида методов — три уровня доступа к сущности: объект (self), класс (cls), ничего. Дальше: инкапсуляция — как спрятать внутренности класса за публичным интерфейсом; @property — вычисляемые атрибуты, которые выглядят как поля. А альтернативные конструкторы ещё не раз выручат в проектах этого курса.

Что выведет код?

Сначала предскажи ответ в голове — это главный навык программиста.

class Temperature:
    def __init__(self, celsius):
        self.celsius = celsius

    @classmethod
    def from_fahrenheit(cls, f):
        return cls((f - 32) * 5 / 9)

t = Temperature.from_fahrenheit(32)
print(t.celsius)
class Box:
    def __init__(self, weight):
        self.weight = weight

    def show(self):
        print(f"Вес: {self.weight}")

box = Box(7)
Box.show(box)
class Math:
    @staticmethod
    def double(x):
        return x * 2

print(Math.double(21))
Проверь себя
0 / 6

1. Первый параметр обычного метода — это...

2. Что получает @classmethod первым параметром?

3. Зачем нужен альтернативный конструктор from_string?

4. Когда уместен @staticmethod?

5. Можно ли вызвать статический метод через экземпляр?

6. cls — это...

Карточки терминов
Запомнено: 0 / 6
Практика

Создайте класс Money: __init__(self, amount) сохраняет сумму; classmethod from_kopecks(kopecks) переводит копейки в рубли (делением на 100) и возвращает новый объект; @staticmethod is_valid_amount(amount) возвращает True для неотрицательных чисел. Создайте объект из 1250 копеек и выведите две строки: сумму и результат проверки 250.

practice.py
Вопросы и ответы по уроку

Чем classmethod отличается от обычного метода?

Обычный метод первым параметром получает экземпляр (self) и работает с его атрибутами. classmethod получает сам класс (cls): ему неважно, сколько объектов существует, — он создаёт новые (альтернативные конструкторы) или читает общие атрибуты класса.

Урок 2: __init__ и self

Когда использовать staticmethod?

Когда метод не трогает ни объект, ни класс: чистая функция, логично живущая внутри класса. Проверки формата, конвертации единиц, вспомогательные расчёты. Если внутри понадобится self или cls — это сигнал сменить вид метода.

Зачем создавать экземпляр через cls, а не через имя класса?

cls указывает на класс, через который вызван метод, включая наследников: Money.from_kopecks(1250) создаст Money, а DiscountMoney.from_kopecks(1250) — DiscountMoney. Жёстко прописанное имя класса сломало бы это поведение.

Можно ли вызывать classmethod и staticmethod на экземпляре?

Да: Python сам передаёт правильный cls или ничего. m.is_valid_amount(250) работает как Money.is_valid_amount(250). Выбор «через класс или через экземпляр» — вопрос читаемости: фабрики и утилиты обычно вызывают через класс.

Понравился урок? Сошлитесь на него

«classmethod нужен тогда, когда методу важен класс: чаще всего это альтернативный конструктор.»

Скопируйте готовую ссылку в формате HTML, Markdown или чистый адрес и вставьте в статью на Habr, VC, Telegram-канал или свой блог — так о проекте узнают новые читатели.

TelegramVK

Похожие уроки по темам

Подобраны автоматически по пересечению тем и ключевых слов.