Зачем использовать classmethod вместо staticmethod?

Я знаю, что они делают, и я видел много примеров обоих, но я не нашел ни одного примера, где мне пришлось бы использовать classmethod вместо того, чтобы заменить его на staticmethod.

Самый распространенный пример classmethod, который я видел, - это для создания нового экземпляра самого класса, например этого (очень упрощенный пример, там не используется метод atm, но вы получить идею):

class Foo:
    @classmethod
    def create_new(cls):
        return cls()

Это приведет к возврату нового экземпляра Foo при вызове foo = Foo.create_new(). Теперь почему я не могу использовать это вместо этого:

class Foo:
    @staticmethod
    def create_new():
        return Foo()

То же самое, почему я должен использовать classmethod поверх staticmethod?

Ответы

Ответ 1

В вашем примере мало различий, но предположим, что вы создали подкласс Foo и вызвали метод create_new в подклассе...

class Bar(Foo):
    pass

obj = Bar.create_new()

... тогда этот базовый класс создаст новый объект Bar...

class Foo:
    @classmethod
    def create_new(cls):
        return cls()

... тогда как этот базовый класс вызовет создание нового объекта Foo...

class Foo:
    @staticmethod
    def create_new():
        return Foo()

... поэтому выбор будет зависеть от того, какое поведение вы хотите.

Ответ 2

Да, эти два класса будут делать то же самое.

Однако теперь представьте подтип этого класса:

class Bar (Foo):
    pass

Теперь вызов Bar.create_new делает что-то другое. Для статического метода вы получаете Foo. Для метода класса вы получите Bar.

Таким образом, важное различие заключается в том, что метод класса получает тип, переданный как параметр.

Ответ 3

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

Это может быть полезно в ситуациях, когда у вас есть унаследованный статический метод, который вы хотите переопределить с другим поведением в подклассе.