Чем @staticmethod отличается от @classmethod?
- Когда использовать 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 нельзя вызвать через экземпляр
Что спросят дальше
Разбор темы
- ООП в Python — классы, свойства, наследование и dataclass
self и __init__, магические методы, property, staticmethod и classmethod, MRO и super, dataclass против namedtuple и Pydantic, ABC и Protocol, метаклассы.
Связанные вопросы
Разбор собеседования с sotto
После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.