Categories
methods oop python python-decorators

Difference between @staticmethod and @classmethod

4364

What is the difference between a function decorated with @staticmethod and one decorated with @classmethod?

3

  • 20

    static methods are sometimes better off as module level functions in python for the sake of cleanliness. With a module function it is easier to import just the function you need and prevent unnecessary “.” syntax (I’m looking at you Objective-C). class methods have more use since they can be used in combination with polymorphism to create “factory pattern” functions. this is because class methods receive the class as an implicit parameter.

    Dec 6, 2017 at 3:44

  • 51

    tl;dr >> when compared to normal methods, the static methods and class methods can also be accessed using the class but unlike class methods, static methods are immutable via inheritance.

    Jul 11, 2018 at 15:02


  • 7

    Related talk by Raymond Hettinger on the topic: youtube.com/watch?v=HTLu2DFOdTg

    – moooeeeep

    Sep 10, 2018 at 9:35

3703

Maybe a bit of example code will help: Notice the difference in the call signatures of foo, class_foo and static_foo:

class A(object):
    def foo(self, x):
        print(f"executing foo({self}, {x})")

    @classmethod
    def class_foo(cls, x):
        print(f"executing class_foo({cls}, {x})")

    @staticmethod
    def static_foo(x):
        print(f"executing static_foo({x})")

a = A()

Below is the usual way an object instance calls a method. The object instance, a, is implicitly passed as the first argument.

a.foo(1)
# executing foo(<__main__.A object at 0xb7dbef0c>, 1)

With classmethods, the class of the object instance is implicitly passed as the first argument instead of self.

a.class_foo(1)
# executing class_foo(<class '__main__.A'>, 1)

You can also call class_foo using the class. In fact, if you define something to be
a classmethod, it is probably because you intend to call it from the class rather than from a class instance. A.foo(1) would have raised a TypeError, but A.class_foo(1) works just fine:

A.class_foo(1)
# executing class_foo(<class '__main__.A'>, 1)

One use people have found for class methods is to create inheritable alternative constructors.


With staticmethods, neither self (the object instance) nor cls (the class) is implicitly passed as the first argument. They behave like plain functions except that you can call them from an instance or the class:

a.static_foo(1)
# executing static_foo(1)

A.static_foo('hi')
# executing static_foo(hi)

Staticmethods are used to group functions which have some logical connection with a class to the class.


foo is just a function, but when you call a.foo you don’t just get the function,
you get a “partially applied” version of the function with the object instance a bound as the first argument to the function. foo expects 2 arguments, while a.foo only expects 1 argument.

a is bound to foo. That is what is meant by the term “bound” below:

print(a.foo)
# <bound method A.foo of <__main__.A object at 0xb7d52f0c>>

With a.class_foo, a is not bound to class_foo, rather the class A is bound to class_foo.

print(a.class_foo)
# <bound method type.class_foo of <class '__main__.A'>>

Here, with a staticmethod, even though it is a method, a.static_foo just returns
a good ‘ole function with no arguments bound. static_foo expects 1 argument, and
a.static_foo expects 1 argument too.

print(a.static_foo)
# <function static_foo at 0xb7d479cc>

And of course the same thing happens when you call static_foo with the class A instead.

print(A.static_foo)
# <function static_foo at 0xb7d479cc>

5

  • 233

    I don’t understand what’s the catch for using staticmethod. we can just use a simple outside-of-class function.

    – Alcott

    Sep 19, 2011 at 3:08

  • 468

    @Alcott: You might want to move a function into a class because it logically belongs with the class. In the Python source code (e.g. multiprocessing,turtle,dist-packages), it is used to “hide” single-underscore “private” functions from the module namespace. Its use, though, is highly concentrated in just a few modules — perhaps an indication that it is mainly a stylistic thing. Though I could not find any example of this, @staticmethod might help organize your code by being overridable by subclasses. Without it you’d have variants of the function floating around in the module namespace.

    – unutbu

    Sep 19, 2011 at 10:34

  • 136

    @Alcott: as unutbu said, static methods are an organization/stylistic feature. Sometimes a module have many classes, and some helper functions are logically tied to a a given class and not to the others, so it makes sense not to “pollute” the module with many “free functions”, and it is better to use a static method than relying on the poor style of mixing classes and function defs together in code just to show they are “related”

    May 3, 2012 at 9:55

  • Of course the above responses to Alcott’s comment also miss the obvious… you can override static methods and class methods in a child class. At this point the distinction between classmethod and staticmethod become extremely important. If one static method calls another static method, it should really be a class method calling cls.some_static_method() so that the child classes can replace the static easily.

    Jan 20 at 23:45

  • @Alcott Staticmethod defines a function, but it does one more thing – it makes the function a class variable. If you happen to want to want a class variable that is a function (and not a method) and don’t want to use the function for anything unrelated to the class, then staticmethod is the idiomatic way to do it.

    – saolof

    Mar 24 at 15:04

917

A staticmethod is a method that knows nothing about the class or instance it was called on. It just gets the arguments that were passed, no implicit first argument. It is basically useless in Python — you can just use a module function instead of a staticmethod.

A classmethod, on the other hand, is a method that gets passed the class it was called on, or the class of the instance it was called on, as first argument. This is useful when you want the method to be a factory for the class: since it gets the actual class it was called on as first argument, you can always instantiate the right class, even when subclasses are involved. Observe for instance how dict.fromkeys(), a classmethod, returns an instance of the subclass when called on a subclass:

>>> class DictSubclass(dict):
...     def __repr__(self):
...         return "DictSubclass"
... 
>>> dict.fromkeys("abc")
{'a': None, 'c': None, 'b': None}
>>> DictSubclass.fromkeys("abc")
DictSubclass
>>> 

9

  • 822

    A staticmethod isn’t useless – it’s a way of putting a function into a class (because it logically belongs there), while indicating that it does not require access to the class.

    Sep 26, 2008 at 10:10

  • 154

    Hence only ‘basically’ useless. Such organization, as well as dependency injection, are valid uses of staticmethods, but since modules, not classes like in Java, are the basic elements of code organization in Python, their use and usefulness is rare.

    Sep 26, 2008 at 13:40

  • 46

    What’s logical about defining a method inside a class, when it has nothing to do with either the class or its instances?

    – Ben James

    Mar 12, 2010 at 9:11


  • 120

    Perhaps for the inheritance sake? Static methods can be inherited and overridden just like instance methods and class methods and the lookup works as expected (unlike in Java). Static methods are not really resolved statically whether called on the class or instance, so the only difference between class and static methods is the implicit first argument.

    – haridsv

    Apr 8, 2010 at 1:32

  • 97

    They also create a cleaner namespace, and makes it easier to understand the function have something to do with the class.

    – Imbrondir

    Aug 22, 2011 at 11:58

189

Basically @classmethod makes a method whose first argument is the class it’s called from (rather than the class instance), @staticmethod does not have any implicit arguments.