Ответ
Параметр cls в методе класса (декорированном @classmethod) представляет собой сам класс, а не его экземпляр (который передается как self в обычных методах).
Это позволяет методу работать с атрибутами класса или создавать экземпляры класса, не имея доступа к конкретному объекту. Основное применение — фабричные методы, которые предоставляют альтернативные способы создания объектов.
Пример: Фабричный метод
Предположим, мы хотим создавать объект User из строки с датой рождения в формате YYYY-MM-DD.
from datetime import date
class User:
def __init__(self, name: str, age: int):
self.name = name
self.age = age
@classmethod
def from_birth_year(cls, name: str, birth_year: int):
"""Альтернативный конструктор для создания пользователя по году рождения."""
current_year = date.today().year
age = current_year - birth_year
# cls() вызывает конструктор __init__ класса User
return cls(name, age)
# Основной способ создания
user1 = User("Alice", 30)
# Использование фабричного метода @classmethod
user2 = User.from_birth_year("Bob", 1995)
print(f"{user2.name} is {user2.age} years old.")
# Вывод: Bob is 29 years old. (для 2024 года)
Ключевые отличия от self:
cls: Ссылается на класс (User). Используется в@classmethod.self: Ссылается на конкретный экземпляр класса (user1,user2). Используется в обычных методах экземпляра.
Ответ 18+ 🔞
А, слушай, вот эта штука с cls в классах — это ж, блядь, чистой воды магия, но не та, что с заклинаниями, а которая реально полезная. Представь себе: обычный метод — это как твой личный швейцар, который работает с конкретной квартирой (self). А @classmethod — это, сука, главный архитектор всего дома, у которого есть чертежи на все квартиры сразу.
Вот смотри, чтобы не быть мудаком, который везде пихает self, когда надо работать со всем классом, придумали эту фишку. cls — это сам класс, целиком, в его первозданной красоте. Не какой-то там отдельный экземпляр, а вся сущность, блядь, целиком.
Основная фишка — это фабричные методы. Ну, то есть альтернативные способы слепить объект, когда стандартный __init__ тебе неудобен, как сиденье унитаза после соседа-слона.
Допустим, у тебя класс User. И ты хочешь его создавать не по возрасту, а по году рождения. Ну, логично же, ёпта! Зачем считать вручную, если можно заставить класс сделать это за тебя?
from datetime import date
class User:
def __init__(self, name: str, age: int):
self.name = name
self.age = age
@classmethod
def from_birth_year(cls, name: str, birth_year: int):
"""Вот тут мы и колдуем. Делаем пользователя из года рождения."""
current_year = date.today().year
age = current_year - birth_year
# А вот тут самое важное! cls() — это волшебный пендель,
# который говорит: "Эй, класс, из которого меня вызвали, создай сам себя с этими параметрами!"
return cls(name, age)
# Стандартный способ, скучный, но надёжный
user1 = User("Алиса", 30)
# А вот это уже круто! Вызываем метод КЛАССА, а не объекта.
# Словно говорим: "User, будь добр, роди мне Боба из 1995 года".
user2 = User.from_birth_year("Боб", 1995)
print(f"{user2.name} is {user2.age} years old.")
# Выведет что-то вроде: Bob is 29 years old. (если на дворе 2024-й, конечно)
И главное, блядь, понимать разницу, а то потом сидишь и думаешь, почему всё ебёт мозг:
self— это ты сам, конкретный, потный, со своими косяками и атрибутами. Это твой личный экземпляр. Обычные методы с ним и работают.cls— это, блин, как бы твой паспорт, твоя родословная. Это сам классUser. И метод с@classmethodработает не с одной тушкой, а со всей концепцией в целом. Он может новых "тебя" создавать, в обход стандартного входа.
Короче, cls — это когда нужно действовать от имени всей фамилии, а не от имени отдельного её члена. Понял, да? А то опять будешь self туда пихать, где не надо, и удивляться, почему всё падает с ошибкой, как ядрёна вошь.