Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
@classmethod декоратор в Python
@classmethod — это встроенный декоратор, который превращает метод в метод класса. Вместо self (экземпляр), получает cls (класс).
Основная различие: instance vs class method
class Person:
species = \"Homo sapiens\" # Переменная класса
def __init__(self, name):
self.name = name # Переменная экземпляра
# Обычный метод экземпляра
def greet(self):
return f\"Hello, I'm {self.name}\"
# Метод класса
@classmethod
def get_species(cls):
return cls.species
# Статический метод (не требует ни self, ни cls)
@staticmethod
def is_human():
return True
# Экземплярный метод
person = Person(\"Alice\")
print(person.greet()) # Hello, I'm Alice
# Методы класса и статический вызываются от класса
print(Person.get_species()) # Homo sapiens
print(Person.is_human()) # True
# Но также можно вызвать от экземпляра
print(person.get_species()) # Homo sapiens
Зачем нужны classmethod
1. Альтернативные конструкторы (factory methods)
Это основное применение. Classmethod позволяет создавать объекты по-разному.
from datetime import datetime
class Date:
def __init__(self, day, month, year):
self.day = day
self.month = month
self.year = year
def __repr__(self):
return f\"Date({self.day}/{self.month}/{self.year})\"
# Альтернативный конструктор из строки
@classmethod
def from_string(cls, date_string):
\"\"\"Создаёт Date из строки 'DD/MM/YYYY'\"\"\"
day, month, year = map(int, date_string.split('/'))
return cls(day, month, year)
# Альтернативный конструктор из timestamp
@classmethod
def from_timestamp(cls, timestamp):
dt = datetime.fromtimestamp(timestamp)
return cls(dt.day, dt.month, dt.year)
# Текущая дата
@classmethod
def today(cls):
today = datetime.now()
return cls(today.day, today.month, today.year)
# Разные способы создания
date1 = Date(15, 3, 2024)
date2 = Date.from_string(\"15/03/2024\")
date3 = Date.today()
print(date1) # Date(15/3/2024)
print(date2) # Date(15/3/2024)
print(date3) # Date(22/3/2026)
2. Работа с наследованием
Classmethod автоматически получит правильный класс при наследовании.
class Animal:
count = 0
def __init__(self, name):
self.name = name
Animal.count += 1
@classmethod
def get_count(cls):
\"\"\"Возвращает количество объектов текущего класса\"\"\"
return cls.count
class Dog(Animal):
count = 0 # Свой счётчик для собак
def __init__(self, name, breed):
self.breed = breed
super().__init__(name)
Dog.count += 1
class Cat(Animal):
count = 0 # Свой счётчик для кошек
def __init__(self, name, color):
self.color = color
super().__init__(name)
Cat.count += 1
# Classmethod автоматически использует правильный класс
dog1 = Dog(\"Rex\", \"Labrador\")
dog2 = Dog(\"Max\", \"Bulldog\")
cat1 = Cat(\"Whiskers\", \"Orange\")
print(Dog.get_count()) # 2 (из Dog.count)
print(Cat.get_count()) # 1 (из Cat.count)
print(Animal.get_count()) # 0 (из Animal.count)
3. Доступ к переменным класса
Classmethod может читать и изменять переменные класса.
class BankAccount:
interest_rate = 0.05 # Переменная класса
def __init__(self, owner, balance=0):
self.owner = owner
self.balance = balance
@classmethod
def set_interest_rate(cls, rate):
\"\"\"Изменяет процентную ставку для всех счётов\"\"\"
cls.interest_rate = rate
@classmethod
def get_interest_rate(cls):
return cls.interest_rate
def apply_interest(self):
\"\"\"Применяет процент к балансу\"\"\"
self.balance *= (1 + self.interest_rate)
# Изменяем ставку для всех счётов
BankAccount.set_interest_rate(0.07)
account1 = BankAccount(\"Alice\", 1000)
print(account1.interest_rate) # 0.07
account1.apply_interest()
print(account1.balance) # 1070.0
4. Реальный пример: JSON сериализация
import json
from datetime import datetime
class Person:
def __init__(self, name, age, birth_date=None):
self.name = name
self.age = age
self.birth_date = birth_date
def to_dict(self):
return {
'name': self.name,
'age': self.age,
'birth_date': self.birth_date.isoformat() if self.birth_date else None
}
def to_json(self):
return json.dumps(self.to_dict())
@classmethod
def from_dict(cls, data):
return cls(
name=data['name'],
age=data['age'],
birth_date=datetime.fromisoformat(data['birth_date']) if data.get('birth_date') else None
)
@classmethod
def from_json(cls, json_string):
data = json.loads(json_string)
return cls.from_dict(data)
# Сериализация
person = Person(\"Bob\", 30, datetime(1994, 5, 15))
json_str = person.to_json()
print(json_str) # {\"name\": \"Bob\", \"age\": 30, \"birth_date\": \"1994-05-15T00:00:00\"}
# Десериализация
person2 = Person.from_json(json_str)
print(person2.name) # Bob
print(person2.age) # 30
5. Правильная работа с наследованием (super с classmethod)
class Base:
@classmethod
def create(cls):
print(f\"Creating {cls.__name__}\")
return cls()
class Derived(Base):
def __init__(self):
self.value = 42
obj = Derived.create() # Creating Derived
print(obj.value) # 42
classmethod vs staticmethod vs обычный метод
| Тип | Получает | Использование |
|---|---|---|
| Обычный метод | self (экземпляр) | Работа с экземпляром |
| @classmethod | cls (класс) | Альтернативные конструкторы, работа с классом |
| @staticmethod | ничего | Утилиты, не связанные с классом |
class Example:
class_var = \"class\"
def __init__(self, value):
self.instance_var = value
def instance_method(self):
return f\"Instance: {self.instance_var}\"
@classmethod
def class_method(cls):
return f\"Class: {cls.class_var}\"
@staticmethod
def static_method():
return \"Static: no access to instance or class\"
example = Example(\"test\")
print(example.instance_method()) # Instance: test
print(example.class_method()) # Class: class
print(example.static_method()) # Static: no access to instance or class
Практические советы
- Используй @classmethod для factory methods — создание объектов по-разному
- Используй @classmethod при наследовании — автоматически выберет правильный класс
- Используй @classmethod для работы с переменными класса — счётчики, глобальные настройки
- Используй @staticmethod для утилит — функции, не связанные с экземпляром или классом
- Используй обычный метод для работы с экземпляром — по умолчанию
@classmethod — это мощный инструмент для создания гибких и масштабируемых классов.