← Назад к вопросам

Что в @classmethod передается первым аргументом?

1.8 Middle🔥 231 комментариев
#Python Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# @classmethod: первый аргумент — cls

Основное правило

В методе, украшенном декоратором @classmethod, первым аргументом всегда передается сам класс (обычно обозначается как cls), а не экземпляр объекта.

class Dog:
    species = 'Canis familiaris'
    
    @classmethod
    def get_species(cls):
        return cls.species

print(Dog.get_species())  # 'Canis familiaris'
print(Dog.get_species.__self__)  # <class 'Dog'>

Отличие от обычного метода

Обычный метод (instance method)

class Dog:
    def __init__(self, name):
        self.name = name
    
    def bark(self):
        # self — экземпляр класса
        print(f'{self.name} says woof!')

dog = Dog('Rex')
dog.bark()  # Rex says woof!

Classmethod

class Dog:
    species = 'Canis familiaris'
    
    @classmethod
    def change_species(cls, new_species):
        # cls — сам класс, не экземпляр
        cls.species = new_species

Dog.change_species('Canis lupus')  # Работает без создания экземпляра
print(Dog.species)  # 'Canis lupus'

Практические примеры

1. Альтернативные конструкторы (factory pattern)

from datetime import datetime

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    @classmethod
    def from_birth_year(cls, name, birth_year):
        age = datetime.now().year - birth_year
        return cls(name, age)

person = Person.from_birth_year('Alice', 1990)
print(person.name, person.age)  # Alice 34

Это удобнее, чем писать отдельные функции, и работает с наследованием.

2. Работа с классовыми переменными

class Config:
    debug = False
    database = 'localhost'
    
    @classmethod
    def set_debug(cls, enabled):
        cls.debug = enabled
    
    @classmethod
    def get_config(cls):
        return {'debug': cls.debug, 'db': cls.database}

Config.set_debug(True)
print(Config.get_config())  # {'debug': True, 'db': 'localhost'}

3. Наследование и переопределение

class Animal:
    name = 'unknown'
    
    @classmethod
    def info(cls):
        return f'This is {cls.name}'

class Dog(Animal):
    name = 'Dog'

class Cat(Animal):
    name = 'Cat'

print(Animal.info())  # This is unknown
print(Dog.info())     # This is Dog
print(Cat.info())     # This is Cat

Ключевое преимущество: cls указывает на конкретный класс, поэтому наследование работает корректно.

4. Счетчик созданных объектов

class Counter:
    count = 0
    
    def __init__(self):
        Counter.count += 1
    
    @classmethod
    def get_count(cls):
        return cls.count

a = Counter()
b = Counter()
c = Counter()

print(Counter.get_count())  # 3

Вызов classmethod

Через класс

class Example:
    @classmethod
    def method(cls):
        print(cls)

Example.method()  # <class '__main__.Example'>

Через экземпляр

obj = Example()
obj.method()  # Тоже работает! cls всё равно будет классом

Сравнение: @staticmethod vs @classmethod vs обычный метод

Обычный метод передает self (экземпляр), @classmethod передает cls (класс), @staticmethod не передает ничего.

class Example:
    class_var = 'value'
    
    def instance_method(self):
        print(self.__class__)  # Доступ к классу через self
    
    @classmethod
    def class_method(cls):
        print(cls)  # Доступ к классу напрямую
        print(cls.class_var)  # Доступ к классовым переменным
    
    @staticmethod
    def static_method():
        print('No cls or self')  # Полностью независимый метод

Когда использовать @classmethod

✅ Для factory методов (альтернативных конструкторов) ✅ Для работы с классовыми переменными ✅ Для операций, не требующих состояния экземпляра ✅ Когда нужно правильное наследование через cls

Вывод

@classmethod передает первым аргументом класс, а не экземпляр. Это мощный инструмент для альтернативных конструкторов, работы с классовыми переменными и написания кода, который корректно работает при наследовании. Запомни: cls — это сам класс, поэтому ты можешь создавать новые экземпляры, вызывать другие методы класса и работать с классовыми переменными.

Что в @classmethod передается первым аргументом? | PrepBro