В чем разница между статическим методом и класс-методом в Python

Ответ

Основное различие заключается в первом аргументе, который они получают (или не получают), что определяет их возможности.

Статический метод (@staticmethod)

Не получает никаких обязательных первых аргументов (self или cls). Это, по сути, обычная функция, помещенная в пространство имен класса для логической группировки. Она не может изменять состояние класса или экземпляра.

Класс-метод (@classmethod)

Получает класс в качестве первого неявного аргумента, который по соглашению называется cls. Это позволяет методу работать с самим классом, например, обращаться к его атрибутам или создавать экземпляры класса (фабричные методы).

Сравнительный пример:

class MyClass:
    class_variable = 10

    def __init__(self, value):
        self.instance_variable = value

    @staticmethod
    def static_method(x, y):
        # Не имеет доступа ни к class_variable, ни к instance_variable
        # Просто утилитарная функция
        return x + y

    @classmethod
    def class_method(cls, value_for_new_instance):
        # Имеет доступ к атрибутам класса, например, cls.class_variable
        print(f"Class variable: {cls.class_variable}")
        # Может создавать экземпляры класса (фабричный метод)
        return cls(value_for_new_instance)

# Вызов без создания экземпляра
print(MyClass.static_method(5, 3))  # Вывод: 8

# Создание экземпляра через класс-метод
instance = MyClass.class_method(100)
print(instance.instance_variable) # Вывод: 100

Когда что использовать:

  • @staticmethod: для утилитарных функций, которые логически связаны с классом, но не зависят от его состояния.
  • @classmethod: для создания альтернативных конструкторов (фабричных методов) или для операций, которые должны работать с классом в целом.

Ответ 18+ 🔞

Вот же ж, опять эти статические методы с класс-методами путают, как будто это одно и то же! Слушай, давай разберёмся, пока мозг не закипел, как чайник.

Представь себе класс — это типа такой дом. Внутри живут обычные методы (они же инстанс-методы), которые знают про конкретную квартиру (self). А ещё там есть два особенных жильца.

Первый — статик-метод (@staticmethod). Это такой отшельник, блядь. Ему похуй на весь дом. Ни тебе self, ни cls он не получает. Вообще. Ноль. Просто функция, которую для порядка в шкаф к классу засунули, чтобы не валялась где попало. Изменить состояние класса или экземпляра? Да ни хуя! Он как калькулятор: дали два числа — получи результат.

Второй — класс-метод (@classmethod). А вот этот парень — завхоз. Он получает на вход сам класс, то есть весь дом целиком. По договорённости этот аргумент зовут cls. И он с этим домом может делать штуки: заглянуть в общие настройки (атрибуты класса) или, например, новых жильцов (экземпляры) создавать. Фабричные методы — это его конёк, ёпта.

Смотри, как это в коде выглядит, чтоб совсем понятно стало:

class MyClass:
    class_variable = 10  # Общая для всех тарелка с печеньками

    def __init__(self, value):
        self.instance_variable = value  # А это личная печенька

    @staticmethod
    def static_method(x, y):
        # Ему вообще похуй на печеньки, свои или общие.
        # Просто сложит что дали и всё.
        return x + y

    @classmethod
    def class_method(cls, value_for_new_instance):
        # Опа, а этот видит общую тарелку!
        print(f"Class variable: {cls.class_variable}")
        # И может новых чуваков в дом заселить (экземпляр создать)
        return cls(value_for_new_instance)

# Вызываем отшельника-статик. Ему даже экземпляр не нужен.
print(MyClass.static_method(5, 3))  # Вывод: 8. Просто математика, блядь.

# А тут завхоз-классметод работает. Создаёт нам новый экземпляр.
instance = MyClass.class_method(100)
print(instance.instance_variable) # Вывод: 100. Новый жилец с личной печенькой.

Так когда что юзать, чтобы не выглядеть как манда с ушами?

  • @staticmethod: Когда у тебя есть утилитарная функция, которая по смыслу привязана к классу, но ей наплевать на его внутреннее состояние. Типа calculate_distance(x1, y1, x2, y2) внутри класса Point. Чистая логика, без доступа к self или cls.
  • @classmethod: Когда тебе нужно работать с классом как с объектом. Самый частый случай — это альтернативные конструкторы (фабрики). Например, from_json(cls, data) или create_default(cls). Или когда метод должен обращаться к атрибутам класса, а не экземпляра.

Вот и вся магия, ёбушки-воробушки. Главное — не путай их, а то получится пиздопроебибна, а не код.