Вопрос с собеседования · Python

Чем @staticmethod отличается от @classmethod?

JuniorООП
Ещё спрашивают так:
  • Когда использовать classmethod?
  • Зачем нужен staticmethod?
  • Что такое альтернативный конструктор?
Коротко

@classmethod получает класс (cls), @staticmethod не получает ничего — это обычная функция внутри класса.

  • classmethod — для альтернативных конструкторов: User.from_json(...)
  • При наследовании cls — это подкласс, поэтому создаётся объект нужного типа

А ещё staticmethod уместен, когда функция логически относится к классу, но не трогает его состояние

Подробно

Есть три вида методов:

  • обычный — первым аргументом получает экземпляр (self), работает с его данными;
  • **@classmethod** — первым аргументом получает класс (cls). Может создавать экземпляры и работать с атрибутами класса. Вызывается и от класса, и от экземпляра;
  • **@staticmethod** — не получает ни экземпляра, ни класса. По сути функция, положенная в пространство имён класса.

Главное применение classmethod — альтернативные конструкторы: datetime.fromtimestamp, dict.fromkeys. Важная деталь: если наследник вызовет Child.from_json(...), в cls придёт Child, и метод создаст объект наследника. С staticmethod так не получится — пришлось бы жёстко написать имя класса.

staticmethod используют для вспомогательных функций, тесно связанных с классом: проверка формата, преобразование значения. Если функция с классом не связана — ей место на уровне модуля.

Пример

import json

class User:
    def __init__(self, name, age):
        self.name, self.age = name, age

    @classmethod
    def from_json(cls, raw):
        data = json.loads(raw)
        return cls(data["name"], data["age"])   # cls — User или наследник

    @staticmethod
    def is_adult(age):
        return age >= 18

class Admin(User):
    pass

a = Admin.from_json('{"name": "Ира", "age": 30}')
type(a)               # Admin
User.is_adult(17)     # False

Что хотят услышать

  • Что получает каждый вид метода первым аргументом.
  • Альтернативный конструктор как главный случай classmethod.
  • Поведение cls при наследовании.
  • Когда staticmethod уместен, а когда лучше функция модуля.

Частые ошибки

  • Писать фабрику через staticmethod с жёстким именем класса.
  • Говорить, что staticmethod нельзя вызвать от экземпляра.

Проверьте себя

Один верный вариант. Подумайте, потом откройте ответ.

Показать варианты и ответ
  • ✗staticmethod получает класс, а classmethod — экземпляр, поэтому конструкторы пишут через staticmethod
  • ✗classmethod не работает при наследовании
  • ✓classmethod получает класс cls (для альтернативных конструкторов), staticmethod — ничего
  • ✗staticmethod нельзя вызвать через экземпляр

Что спросят дальше

Разбор темы

Связанные вопросы

Партнёр платформы

Разбор собеседования с sotto

После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.

Разбор собеседования