Что в @classmethod передается первым аргументом?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
# @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 — это сам класс, поэтому ты можешь создавать новые экземпляры, вызывать другие методы класса и работать с классовыми переменными.