What is the difference between @staticmethod and @classmethod in Python?
Asked Answered
E

36

4645

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

Expensive answered 25/9, 2008 at 21:1 Comment(3)
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.Touchwood
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.Villeinage
Related talk by Raymond Hettinger on the topic: youtube.com/watch?v=HTLu2DFOdTgBundelkhand
F
3902

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>
Flexion answered 3/11, 2009 at 19:13 Comment(6)
I don't understand what's the catch for using staticmethod. we can just use a simple outside-of-class function.Innocent
@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.Flexion
@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"Tien
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.Bohs
@Innocent 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.Procter
Could @Flexion please clarify if this answer still applies to Python 3? It is not completely clear, although I see the 3rd-party edit that added f-strings. A comment on what changed between Python 2 and 3 would also be appreciated!Selden
S
955

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.

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
>>> 
Scintillant answered 25/9, 2008 at 21:5 Comment(10)
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.Divulsion
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.Scintillant
What's logical about defining a method inside a class, when it has nothing to do with either the class or its instances?Codeine
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.Decline
They also create a cleaner namespace, and makes it easier to understand the function have something to do with the class.Klimt
@BenJames: A staticmethod should have something to do with the class its defined in, it just doesn't need either class nor instance data to do its job. (see stackoverflow.com/questions/7855237)Transversal
So which is better: having a Math class with methods like sin, cos, etc, or having a Math module with functions sin, cos, etc. Seems to me that the latter would be preferable, so I'm hard pressed to think of a possible case where staticmethod would be useful. Helper methods I suppose are a potential case, but if a helper is so general as to not need anything from the class or a class instance, you really do have to wonder if it would be better served as a utility routine in a library.Asp
When you have a class instance its often simpler to call inst.method() rather than module.method(). Sometimes you don't even know which module you're using, Python is a dynamic language after all...Geographer
-1: This answer A) gives a very corner-case feature of class method as an explanation of its utility (so they are only useful when subclassing to allow you the name of the subclass, really?), and B) implies "static methods should be module methods", which, although they semantically are, it makes a lot or sense to use them if your module defines many classes, and a given helper function only applies to a given class. So a very poor answer with lots of misconceptions imho.Tien
> "It is basically useless in Python" This may not be politically correct but I would strongly recommend not to use @classmethod and @staticmethod but just skip this information. Why? The beauty of Python (in contrast to Java or C) is that its code is very compact and the inventors of Python make a lot of implicit assumptions for you that make sense in 99% of cases. There may be good reasons for not adhering to this concept. But then its much better to look around for alternatives rather than over decorating Python code.Merrileemerrili
O
194

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.

Ochs answered 25/9, 2008 at 21:7 Comment(1)
The other answers add unnecessary confusion to a simple answer. This is literally the only think that changes.Resinate
S
140

To decide whether to use @staticmethod or @classmethod you have to look inside your method. If your method accesses other variables/methods in your class then use @classmethod. On the other hand, if your method does not touches any other parts of the class then use @staticmethod.

class Apple:

    _counter = 0

    @staticmethod
    def about_apple():
        print('Apple is good for you.')

        # note you can still access other member of the class
        # but you have to use the class instance 
        # which is not very nice, because you have repeat yourself
        # 
        # For example:
        # @staticmethod
        #    print('Number of apples have been juiced: %s' % Apple._counter)
        #
        # @classmethod
        #    print('Number of apples have been juiced: %s' % cls._counter)
        #
        #    @classmethod is especially useful when you move your function to another class,
        #       you don't have to rename the referenced class 

    @classmethod
    def make_apple_juice(cls, number_of_apples):
        print('Making juice:')
        for i in range(number_of_apples):
            cls._juice_this(i)

    @classmethod
    def _juice_this(cls, apple):
        print('Juicing apple %d...' % apple)
        cls._counter += 1
Switchboard answered 22/4, 2016 at 15:40 Comment(4)
what would be the advantage of classmethod and cls._counter vs. staticmethod and Apple._counterAvraham
cls._counter would still be cls._counter even if the code is put in a different class, or the class name is changed. Apple._counter is specific for the Apple class; for a different class, or when the class name is changed, you would need to change the referenced class.Flowerage
I hope by "move" you don't mean "copy" lolLamoreaux
why even bother with the decorator in that case, your description does not really clarifyConstitutionally
H
127

Official python docs:

@classmethod

A class method receives the class as implicit first argument, just like an instance method receives the instance. To declare a class method, use this idiom:

class C:
    @classmethod
    def f(cls, arg1, arg2, ...): ... 

The @classmethod form is a function decorator – see the description of function definitions in Function definitions for details.

It can be called either on the class (such as C.f()) or on an instance (such as C().f()). The instance is ignored except for its class. If a class method is called for a derived class, the derived class object is passed as the implied first argument.

Class methods are different than C++ or Java static methods. If you want those, see staticmethod() in this section.

@staticmethod

A static method does not receive an implicit first argument. To declare a static method, use this idiom:

class C:
    @staticmethod
    def f(arg1, arg2, ...): ... 

The @staticmethod form is a function decorator – see the description of function definitions in Function definitions for details.

It can be called either on the class (such as C.f()) or on an instance (such as C().f()). The instance is ignored except for its class.

Static methods in Python are similar to those found in Java or C++. For a more advanced concept, see classmethod() in this section.

Haywoodhayyim answered 3/11, 2009 at 19:23 Comment(3)
Isn't there an error in docs? Shouldn't be at staticmethod: "The instance and its class are both ignored." instead of "The instance is ignored except for its class."?Bumpkin
It may be a cut-and-paste error, but strictly speaking you can't call a method on a class if you ignore the class.Appropriation
You are wrong! "static members" in Java are equivalent to "class members" in Python (the difference is in Java you can access a public static attribute from an object but in Python, you can not). "static methods" in Java are equivalent to "classmethod" in Python that can access the class state (class members) "staticmethod" in Python is a relatively useless method that does not access the class state nor instance state and is like a pure function out of the class definition.Odo
T
97

Here is a short article on this question

@staticmethod function is nothing more than a function defined inside a class. It is callable without instantiating the class first. It’s definition is immutable via inheritance.

@classmethod function also callable without instantiating the class, but its definition follows Sub class, not Parent class, via inheritance. That’s because the first argument for @classmethod function must always be cls (class).

Tropophilous answered 3/11, 2009 at 19:2 Comment(4)
So does that mean that by using a staticmethod I am always bound to the Parent class and with the classmethod I am bound the class that I declare the classmethod in (in this case the sub class)?Allele
No. By using a staticmethod you aren't bound at all; there is no implicit first parameter. By using classmethod, you get as implicit first parameter the class you called the method on (if you called it directly on a class), or the class of the instance you called the method on (if you called it on an instance).Amphigory
Could be expanded a bit to show that, by having a class as a first argument, class methods have direct access to other class attributes and methods, while static methods do not (they would need to hardcode MyClass.attr for that)Tien
"It’s definition is immutable via inheritance." doesn't make any sense in Python, you can override a static method just fine.Resinate
F
75

What is the difference between @staticmethod and @classmethod in Python?

You may have seen Python code like this pseudocode, which demonstrates the signatures of the various method types and provides a docstring to explain each:

class Foo(object):

    def a_normal_instance_method(self, arg_1, kwarg_2=None):
        '''
        Return a value that is a function of the instance with its
        attributes, and other arguments such as arg_1 and kwarg2
        '''

    @staticmethod
    def a_static_method(arg_0):
        '''
        Return a value that is a function of arg_0. It does not know the 
        instance or class it is called from.
        '''

    @classmethod
    def a_class_method(cls, arg1):
        '''
        Return a value that is a function of the class and other arguments.
        respects subclassing, it is called with the class it is called from.
        '''

The Normal Instance Method

First I'll explain a_normal_instance_method. This is precisely called an "instance method". When an instance method is used, it is used as a partial function (as opposed to a total function, defined for all values when viewed in source code) that is, when used, the first of the arguments is predefined as the instance of the object, with all of its given attributes. It has the instance of the object bound to it, and it must be called from an instance of the object. Typically, it will access various attributes of the instance.

For example, this is an instance of a string:

', '

if we use the instance method, join on this string, to join another iterable, it quite obviously is a function of the instance, in addition to being a function of the iterable list, ['a', 'b', 'c']:

>>> ', '.join(['a', 'b', 'c'])
'a, b, c'

Bound methods

Instance methods can be bound via a dotted lookup for use later.

For example, this binds the str.join method to the ':' instance:

>>> join_with_colons = ':'.join 

And later we can use this as a function that already has the first argument bound to it. In this way, it works like a partial function on the instance:

>>> join_with_colons('abcde')
'a:b:c:d:e'
>>> join_with_colons(['FF', 'FF', 'FF', 'FF', 'FF', 'FF'])
'FF:FF:FF:FF:FF:FF'

Static Method

The static method does not take the instance as an argument.

It is very similar to a module level function.

However, a module level function must live in the module and be specially imported to other places where it is used.

If it is attached to the object, however, it will follow the object conveniently through importing and inheritance as well.

An example of a static method is str.maketrans, moved from the string module in Python 3. It makes a translation table suitable for consumption by str.translate. It does seem rather silly when used from an instance of a string, as demonstrated below, but importing the function from the string module is rather clumsy, and it's nice to be able to call it from the class, as in str.maketrans

# demonstrate same function whether called from instance or not:
>>> ', '.maketrans('ABC', 'abc')
{65: 97, 66: 98, 67: 99}
>>> str.maketrans('ABC', 'abc')
{65: 97, 66: 98, 67: 99}

In python 2, you have to import this function from the increasingly less useful string module:

>>> import string
>>> 'ABCDEFG'.translate(string.maketrans('ABC', 'abc'))
'abcDEFG'

Class Method

A class method is a similar to an instance method in that it takes an implicit first argument, but instead of taking the instance, it takes the class. Frequently these are used as alternative constructors for better semantic usage and it will support inheritance.

The most canonical example of a builtin classmethod is dict.fromkeys. It is used as an alternative constructor of dict, (well suited for when you know what your keys are and want a default value for them.)

>>> dict.fromkeys(['a', 'b', 'c'])
{'c': None, 'b': None, 'a': None}

When we subclass dict, we can use the same constructor, which creates an instance of the subclass.

>>> class MyDict(dict): 'A dict subclass, use to demo classmethods'
>>> md = MyDict.fromkeys(['a', 'b', 'c'])
>>> md
{'a': None, 'c': None, 'b': None}
>>> type(md)
<class '__main__.MyDict'>

See the pandas source code for other similar examples of alternative constructors, and see also the official Python documentation on classmethod and staticmethod.

Fumigant answered 23/1, 2015 at 20:1 Comment(0)
S
63

I started learning programming language with C++ and then Java and then Python and so this question bothered me a lot as well, until I understood the simple usage of each.

Class Method: Python unlike Java and C++ doesn't have constructor overloading. And so to achieve this you could use classmethod. Following example will explain this

Let's consider we have a Person class which takes two arguments first_name and last_name and creates the instance of Person.

class Person(object):

    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

Now, if the requirement comes where you need to create a class using a single name only, just a first_name, you can't do something like this in Python.

This will give you an error when you will try to create an object (instance).

class Person(object):

    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

    def __init__(self, first_name):
        self.first_name = first_name

However, you could achieve the same thing using @classmethod as mentioned below

class Person(object):

    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

    @classmethod
    def get_person(cls, first_name):
        return cls(first_name, "")

Static Method: This is rather simple, it's not bound to instance or class and you can simply call that using class name.

So let's say in above example you need a validation that first_name should not exceed 20 characters, you can simply do this.

@staticmethod  
def validate_name(name):
    return len(name) <= 20

and you could simply call using class name

Person.validate_name("Gaurang Shah")
Stupefacient answered 10/10, 2017 at 10:10 Comment(1)
It's an old post, but more pythonic way to achieve constructor accepting either one or two arguments would be using def __init__(self, first_name, last_name="") instead of classmethod get_person. Also result will be exactly the same in this case.Hagi
J
61

Only the first argument differs:

  • normal method: the current object is automatically passed as an (additional) first argument
  • classmethod: the class of the current object is automatically passed as an (additional) fist argument
  • staticmethod: no extra arguments are automatically passed. What you passed to the function is what you get.

In more detail...

normal method

The "standard" method, as in every object oriented language. When an object's method is called, it is automatically given an extra argument self as its first argument. That is, method

def f(self, x, y)

must be called with 2 arguments. self is automatically passed, and it is the object itself. Similar to the this that magically appears in eg. java/c++, only in python it is shown explicitly.

actually, the first argument does not have to be called self, but it's the standard convention, so keep it

class method

When the method is decorated

@classmethod
def f(cls, x, y)

the automatically provided argument is not self, but the class of self.

static method

When the method is decorated

@staticmethod
def f(x, y)

the method is not given any automatic argument at all. It is only given the parameters that it is called with.

usages

  • classmethod is mostly used for alternative constructors.
  • staticmethod does not use the state of the object, or even the structure of the class itself. It could be a function external to a class. It only put inside the class for grouping functions with similar functionality (for example, like Java's Math class static methods)
class Point
    def __init__(self, x, y):
        self.x = x
        self.y = y

    @classmethod
    def frompolar(cls, radius, angle):
        """The `cls` argument is the `Point` class itself"""
        return cls(radius * cos(angle), radius * sin(angle))

    @staticmethod
    def angle(x, y):
        """this could be outside the class, but we put it here 
just because we think it is logically related to the class."""
        return atan(y, x)


p1 = Point(3, 2)
p2 = Point.frompolar(3, pi/4)

angle = Point.angle(3, 2)

Jeri answered 21/5, 2019 at 10:47 Comment(2)
This is the best answer out of the bunch above. It is clear with good and concise examples. The other examples leave out some details.Scarificator
this is the only answer that explains this concept very well. i was learn graphql for apis on python and some use classmethod while the others use staticmethod under their class mutation. this brought me to the reason why they are been used that way and this here really provided answers to my curiorcity. thank youSox
J
49

I think a better question is "When would you use @classmethod vs @staticmethod?"

@classmethod allows you easy access to private members that are associated to the class definition. this is a great way to do singletons, or factory classes that control the number of instances of the created objects exist.

@staticmethod provides marginal performance gains, but I have yet to see a productive use of a static method within a class that couldn't be achieved as a standalone function outside the class.

Joellajoelle answered 19/5, 2015 at 15:27 Comment(1)
This question mentions access of private class members. I want to highlight that (depending on your definition of private), @staticmethods have a different access level to @classmethods. The former shouldn't access class private class membersTelecast
Q
39

Static Methods:

  • Simple functions with no self argument.
  • Work on class attributes; not on instance attributes.
  • Can be called through both class and instance.
  • The built-in function staticmethod()is used to create them.

Benefits of Static Methods:

  • It localizes the function name in the classscope
  • It moves the function code closer to where it is used
  • More convenient to import versus module-level functions since each method does not have to be specially imported

    @staticmethod
    def some_static_method(*args, **kwds):
        pass
    

Class Methods:

  • Functions that have first argument as classname.
  • Can be called through both class and instance.
  • These are created with classmethod in-built function.

     @classmethod
     def some_class_method(cls, *args, **kwds):
         pass
    
Queridas answered 3/10, 2016 at 10:41 Comment(0)
A
38

@decorators were added in python 2.4 If you're using python < 2.4 you can use the classmethod() and staticmethod() function.

For example, if you want to create a factory method (A function returning an instance of a different implementation of a class depending on what argument it gets) you can do something like:

class Cluster(object):

    def _is_cluster_for(cls, name):
        """
        see if this class is the cluster with this name
        this is a classmethod
        """ 
        return cls.__name__ == name
    _is_cluster_for = classmethod(_is_cluster_for)

    #static method
    def getCluster(name):
        """
        static factory method, should be in Cluster class
        returns a cluster object for the given name
        """
        for cls in Cluster.__subclasses__():
            if cls._is_cluster_for(name):
                return cls()
    getCluster = staticmethod(getCluster)

Also observe that this is a good example for using a classmethod and a static method, The static method clearly belongs to the class, since it uses the class Cluster internally. The classmethod only needs information about the class, and no instance of the object.

Another benefit of making the _is_cluster_for method a classmethod is so a subclass can decide to change it's implementation, maybe because it is pretty generic and can handle more than one type of cluster, so just checking the name of the class would not be enough.

Angadresma answered 24/2, 2012 at 9:32 Comment(0)
W
33

Let me tell the similarity between a method decorated with @classmethod vs @staticmethod first.

Similarity: Both of them can be called on the Class itself, rather than just the instance of the class. So, both of them in a sense are Class's methods.

Difference: A classmethod will receive the class itself as the first argument, while a staticmethod does not.

So a static method is, in a sense, not bound to the Class itself and is just hanging in there just because it may have a related functionality.

>>> class Klaus:
        @classmethod
        def classmthd(*args):
            return args

        @staticmethod
        def staticmthd(*args):
            return args

# 1. Call classmethod without any arg
>>> Klaus.classmthd()  
(__main__.Klaus,)  # the class gets passed as the first argument

# 2. Call classmethod with 1 arg
>>> Klaus.classmthd('chumma')
(__main__.Klaus, 'chumma')

# 3. Call staticmethod without any arg
>>> Klaus.staticmthd()  
()

# 4. Call staticmethod with 1 arg
>>> Klaus.staticmthd('chumma')
('chumma',)
Winfield answered 14/1, 2018 at 14:7 Comment(1)
but why would you want to use one instead of the other? what is a real world use case?Avelinaaveline
U
29

@staticmethod just disables the default function as method descriptor. classmethod wraps your function in a container callable that passes a reference to the owning class as first argument:

>>> class C(object):
...  pass
... 
>>> def f():
...  pass
... 
>>> staticmethod(f).__get__(None, C)
<function f at 0x5c1cf0>
>>> classmethod(f).__get__(None, C)
<bound method type.f of <class '__main__.C'>>

As a matter of fact, classmethod has a runtime overhead but makes it possible to access the owning class. Alternatively I recommend using a metaclass and putting the class methods on that metaclass:

>>> class CMeta(type):
...  def foo(cls):
...   print cls
... 
>>> class C(object):
...  __metaclass__ = CMeta
... 
>>> C.foo()
<class '__main__.C'>
Ultraconservative answered 25/9, 2008 at 21:24 Comment(1)
One possible downside of a metaclass for this that immediately occurs to me is that you can't call the classmethod directly on an instance. c = C(); c.foo() raises AttributeError, you'd have to do type(c).foo(). This might also be considered a feature - I can't think of why you'd want to though.Fumigant
S
26

The definitive guide on how to use static, class or abstract methods in Python is one good link for this topic, and summary it as following.

@staticmethod function is nothing more than a function defined inside a class. It is callable without instantiating the class first. It’s definition is immutable via inheritance.

  • Python does not have to instantiate a bound-method for object.
  • It eases the readability of the code, and it does not depend on the state of object itself;

@classmethod function also callable without instantiating the class, but its definition follows Sub class, not Parent class, via inheritance, can be overridden by subclass. That’s because the first argument for @classmethod function must always be cls (class).

  • Factory methods, that are used to create an instance for a class using for example some sort of pre-processing.
  • Static methods calling static methods: if you split a static methods in several static methods, you shouldn't hard-code the class name but use class methods
Sinless answered 16/11, 2015 at 2:0 Comment(1)
Thanks @Sinless - the inherited immutability of static function is the key difference it seemsAtaliah
A
26

Another consideration with respect to staticmethod vs classmethod comes up with inheritance. Say you have the following class:

class Foo(object):
    @staticmethod
    def bar():
        return "In Foo"

And you then want to override bar() in a child class:

class Foo2(Foo):
    @staticmethod
    def bar():
        return "In Foo2"

This works, but note that now the bar() implementation in the child class (Foo2) can no longer take advantage of anything specific to that class. For example, say Foo2 had a method called magic() that you want to use in the Foo2 implementation of bar():

class Foo2(Foo):
    @staticmethod
    def bar():
        return "In Foo2"
    @staticmethod
    def magic():
        return "Something useful you'd like to use in bar, but now can't" 

The workaround here would be to call Foo2.magic() in bar(), but then you're repeating yourself (if the name of Foo2 changes, you'll have to remember to update that bar() method).

To me, this is a slight violation of the open/closed principle, since a decision made in Foo is impacting your ability to refactor common code in a derived class (ie it's less open to extension). If bar() were a classmethod we'd be fine:

class Foo(object):
    @classmethod
    def bar(cls):
        return "In Foo"

class Foo2(Foo):
    @classmethod
    def bar(cls):
        return "In Foo2 " + cls.magic()
    @classmethod
    def magic(cls):
        return "MAGIC"

print Foo2().bar()

Gives: In Foo2 MAGIC

Also: historical note: Guido Van Rossum (Python's creator) once referred to staticmethod's as "an accident": https://mail.python.org/pipermail/python-ideas/2012-May/014969.html

we all know how limited static methods are. (They're basically an accident -- back in the Python 2.2 days when I was inventing new-style classes and descriptors, I meant to implement class methods but at first I didn't understand them and accidentally implemented static methods first. Then it was too late to remove them and only provide class methods.

Also: https://mail.python.org/pipermail/python-ideas/2016-July/041189.html

Honestly, staticmethod was something of a mistake -- I was trying to do something like Java class methods but once it was released I found what was really needed was classmethod. But it was too late to get rid of staticmethod.

Asp answered 29/9, 2016 at 17:2 Comment(0)
J
13

The difference occurs when there is inheritance.

Suppose that there are two classes -- Parent and Child. If one wants to use @staticmethod, print_name method should be written twice because the name of the class should be written in the print line.

class Parent:
   _class_name = "Parent"

   @staticmethod
   def print_name():
       print(Parent._class_name)


class Child(Parent):
   _class_name = "Child"

   @staticmethod
   def print_name():
       print(Child._class_name)


Parent.print_name()
Child.print_name()

However, for @classmethod, it is not required to write print_name method twice.

class Parent:
    _class_name = "Parent"

    @classmethod
    def print_name(cls):
        print(cls._class_name)


class Child(Parent):
    _class_name = "Child"


Parent.print_name()
Child.print_name()
Joyejoyful answered 17/3, 2021 at 11:25 Comment(1)
Liked very much the simplicity of this answer. Wish could have given 100 votes for it.Considerate
P
11

I will try to explain the basic difference using an example.

class A(object):
    x = 0

    def say_hi(self):
        pass

    @staticmethod
    def say_hi_static():
        pass

    @classmethod
    def say_hi_class(cls):
        pass

    def run_self(self):
        self.x += 1
        print self.x # outputs 1
        self.say_hi()
        self.say_hi_static()
        self.say_hi_class()

    @staticmethod
    def run_static():
        print A.x  # outputs 0
        # A.say_hi() #  wrong
        A.say_hi_static()
        A.say_hi_class()

    @classmethod
    def run_class(cls):
        print cls.x # outputs 0
        # cls.say_hi() #  wrong
        cls.say_hi_static()
        cls.say_hi_class()

1 - we can directly call static and classmethods without initializing

# A.run_self() #  wrong
A.run_static()
A.run_class()

2- Static method cannot call self method but can call other static and classmethod

3- Static method belong to class and will not use object at all.

4- Class method are not bound to an object but to a class.

Prophets answered 20/9, 2016 at 9:3 Comment(0)
H
11

Instance Method:

+ Can modify object instance state

+ Can modify class state

Class Method:

- Can't modify object instance state

+ Can modify class state

Static Method:

- Can't modify object instance state

- Can't modify class state

class MyClass:
    ''' 
    Instance method has a mandatory first attribute self which represent the instance itself. 
    Instance method must be called by a instantiated instance.
    '''
    def method(self):
        return 'instance method called', self
    
    '''
    Class method has a mandatory first attribute cls which represent the class itself. 
    Class method can be called by an instance or by the class directly. 
    Its most common using scenario is to define a factory method.
    '''
    @classmethod
    def class_method(cls):
        return 'class method called', cls
    
    '''
    Static method doesn’t have any attributes of instances or the class. 
    It also can be called by an instance or by the class directly. 
    Its most common using scenario is to define some helper or utility functions which are closely relative to the class.
    '''
    @staticmethod
    def static_method():
        return 'static method called'


obj = MyClass()
print(obj.method())
print(obj.class_method()) # MyClass.class_method()
print(obj.static_method()) # MyClass.static_method()

output:

('instance method called', <__main__.MyClass object at 0x100fb3940>)
('class method called', <class '__main__.MyClass'>)
static method called

The instance method we actually had access to the object instance , right so this was an instance off a my class object whereas with the class method we have access to the class itself. But not to any of the objects, because the class method doesn't really care about an object existing. However you can both call a class method and static method on an object instance. This is going to work it doesn't really make a difference, so again when you call static method here it's going to work and it's going to know which method you want to call.

The Static methods are used to do some utility tasks, and class methods are used for factory methods. The factory methods can return class objects for different use cases.

And finally, a short example for better understanding:

class Student:
    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

    @classmethod
    def get_from_string(cls, name_string: str):
        first_name, last_name = name_string.split()
        if Student.validate_name(first_name) and Student.validate_name(last_name):
            return cls(first_name, last_name)
        else:
            print('Invalid Names')

    @staticmethod
    def validate_name(name):
        return len(name) <= 10


stackoverflow_student = Student.get_from_string('Name Surname')
print(stackoverflow_student.first_name) # Name
print(stackoverflow_student.last_name) # Surname
Handwoven answered 7/11, 2020 at 20:16 Comment(0)
I
11

Python comes with several built-in decorators. The big three are:

@classmethod
@staticmethod
@property

First let's note that any function of a class can be called with instance of this class (after we initialized this class).

@classmethod is the way to call function not only as an instance of a class but also directly by the class itself as its first argument.

@staticmethod is 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 (so we don't need to use self in function definition).

Let's consider the following class:

class DecoratorTest(object):

    def __init__(self):
        pass

    def doubler(self, x):
        return x*2

    @classmethod
    def class_doubler(cls, x): 
        """
        We need to use 'cls' instead of 'self'; 
        'cls' references the class instead of 
        an instance of the class
        """
        return x*2

    @staticmethod
    def static_doubler(x): 
        """
        No need to add 'self' here;
        static_doubler() could just be 
        a function outside the class.
        """
        return x*2

Let's see how it works:

decor = DecoratorTest()

print(decor.doubler(5))
# 10

# a call with an instance of a class
print(decor.class_doubler(5)) 
# 10

# a direct call by the class itself
print(DecoratorTest.class_doubler(5)) 
# 10

# staticmethod can be called the same as classmethod.

# as an instance of the class
print(decor.static_doubler(5))
# 10

# or as a direct call 
print(DecoratorTest.static_doubler(5))
# 10

Here you can see some use cases for those methods.

Bonus: you can read about @property decorator here

Inflight answered 16/1, 2021 at 19:58 Comment(0)
D
8

@classmethod : can be used to create a shared global access to all the instances created of that class..... like updating a record by multiple users.... I particulary found it use ful when creating singletons as well..:)

@static method: has nothing to do with the class or instance being associated with ...but for readability can use static method

Deoxyribonuclease answered 20/9, 2017 at 16:57 Comment(0)
T
8

A class method receives the class as implicit first argument, just like an instance method receives the instance. It is a method which is bound to the class and not the object of the class.It has access to the state of the class as it takes a class parameter that points to the class and not the object instance. It can modify a class state that would apply across all the instances of the class. For example it can modify a class variable that will be applicable to all the instances.

On the other hand, a static method does not receive an implicit first argument, compared to class methods or instance methods. And can’t access or modify class state. It only belongs to the class because from design point of view that is the correct way. But in terms of functionality is not bound, at runtime, to the class.

as a guideline, use static methods as utilities, use class methods for example as factory . Or maybe to define a singleton. And use instance methods to model the state and behavior of instances.

Hope I was clear !

Tuneberg answered 20/11, 2019 at 11:48 Comment(0)
T
7

My contribution demonstrates the difference amongst @classmethod, @staticmethod, and instance methods, including how an instance can indirectly call a @staticmethod. But instead of indirectly calling a @staticmethod from an instance, making it private may be more "pythonic." Getting something from a private method isn't demonstrated here but it's basically the same concept.

#!python3

from os import system
system('cls')
# %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %

class DemoClass(object):
    # instance methods need a class instance and
    # can access the instance through 'self'
    def instance_method_1(self):
        return 'called from inside the instance_method_1()'

    def instance_method_2(self):
        # an instance outside the class indirectly calls the static_method
        return self.static_method() + ' via instance_method_2()'

    # class methods don't need a class instance, they can't access the
    # instance (self) but they have access to the class itself via 'cls'
    @classmethod
    def class_method(cls):
        return 'called from inside the class_method()'

    # static methods don't have access to 'cls' or 'self', they work like
    # regular functions but belong to the class' namespace
    @staticmethod
    def static_method():
        return 'called from inside the static_method()'
# %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %

# works even if the class hasn't been instantiated
print(DemoClass.class_method() + '\n')
''' called from inside the class_method() '''

# works even if the class hasn't been instantiated
print(DemoClass.static_method() + '\n')
''' called from inside the static_method() '''
# %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %

# >>>>> all methods types can be called on a class instance <<<<<
# instantiate the class
democlassObj = DemoClass()

# call instance_method_1()
print(democlassObj.instance_method_1() + '\n')
''' called from inside the instance_method_1() '''

# # indirectly call static_method through instance_method_2(), there's really no use
# for this since a @staticmethod can be called whether the class has been
# instantiated or not
print(democlassObj.instance_method_2() + '\n')
''' called from inside the static_method() via instance_method_2() '''

# call class_method()
print(democlassObj.class_method() + '\n')
'''  called from inside the class_method() '''

# call static_method()
print(democlassObj.static_method())
''' called from inside the static_method() '''

"""
# whether the class is instantiated or not, this doesn't work
print(DemoClass.instance_method_1() + '\n')
'''
TypeError: TypeError: unbound method instancemethod() must be called with
DemoClass instance as first argument (got nothing instead)
'''
"""
Titre answered 25/6, 2018 at 2:38 Comment(0)
F
7

You might want to consider the difference between:

class A:
    def foo():  # no self parameter, no decorator
        pass

and

class B:
    @staticmethod
    def foo():  # no self parameter
        pass

This has changed between python2 and python3:

python2:

>>> A.foo()
TypeError
>>> A().foo()
TypeError
>>> B.foo()
>>> B().foo()

python3:

>>> A.foo()
>>> A().foo()
TypeError
>>> B.foo()
>>> B().foo()

So using @staticmethod for methods only called directly from the class has become optional in python3. If you want to call them from both class and instance, you still need to use the @staticmethod decorator.

The other cases have been well covered by unutbus answer.

Flabby answered 24/1, 2019 at 12:56 Comment(0)
N
4

Class methods, as the name suggests, are used to make changes to classes and not the objects. To make changes to classes, they will modify the class attributes(not object attributes), since that is how you update classes. This is the reason that class methods take the class(conventionally denoted by 'cls') as the first argument.

class A(object):
    m=54

    @classmethod
    def class_method(cls):
        print "m is %d" % cls.m

Static methods on the other hand, are used to perform functionalities that are not bound to the class i.e. they will not read or write class variables. Hence, static methods do not take classes as arguments. They are used so that classes can perform functionalities that are not directly related to the purpose of the class.

class X(object):
    m=54 #will not be referenced

    @staticmethod
    def static_method():
        print "Referencing/calling a variable or function outside this class. E.g. Some global variable/function."
Normative answered 1/12, 2017 at 10:38 Comment(1)
methods don't always make changesTelecast
M
4

I think giving a purely Python version of staticmethod and classmethod would help to understand the difference between them at language level (Refers to Descriptor Howto Guide).

Both of them are non-data descriptors (It would be easier to understand them if you are familiar with descriptors first).

class StaticMethod(object):
    "Emulate PyStaticMethod_Type() in Objects/funcobject.c"

    def __init__(self, f):
        self.f = f

    def __get__(self, obj, objtype=None):
        return self.f


class ClassMethod(object):
    "Emulate PyClassMethod_Type() in Objects/funcobject.c"
    def __init__(self, f):
        self.f = f

    def __get__(self, obj, cls=None):
        def inner(*args, **kwargs):
            if cls is None:
                cls = type(obj)
            return self.f(cls, *args, **kwargs)
        return inner
Manheim answered 20/11, 2019 at 9:50 Comment(0)
G
3

Analyze @staticmethod literally providing different insights.

A normal method of a class is an implicit dynamic method which takes the instance as first argument.
In contrast, a staticmethod does not take the instance as first argument, so is called 'static'.

A staticmethod is indeed such a normal function the same as those outside a class definition.
It is luckily grouped into the class just in order to stand closer where it is applied, or you might scroll around to find it.

Grobe answered 12/12, 2017 at 9:40 Comment(0)
A
3

First let's start with an example code that we'll use to understand both concepts:

class Employee:

    NO_OF_EMPLOYEES = 0
  
    def __init__(self, first_name, last_name, salary):
        self.first_name = first_name
        self.last_name = last_name
        self.salary = salary
        self.increment_employees()

    def give_raise(self, amount):
        self.salary += amount

    @classmethod
    def employee_from_full_name(cls, full_name, salary):
        split_name = full_name.split(' ')
        first_name = split_name[0]
        last_name = split_name[1]
        return cls(first_name, last_name, salary)

    @classmethod
    def increment_employees(cls):
        cls.NO_OF_EMPLOYEES += 1

    @staticmethod
    def get_employee_legal_obligations_txt():
        legal_obligations = """
        1. An employee must complete 8 hours per working day
        2. ...
        """
        return legal_obligations

Class method

A class method accepts the class itself as an implicit argument and -optionally- any other arguments specified in the definition. It’s important to understand that a class method, does not have access to object instances (like instance methods do). Therefore, class methods cannot be used to alter the state of an instantiated object but instead, they are capable of changing the class state which is shared amongst all the instances of that class. Class methods are typically useful when we need to access the class itself — for example, when we want to create a factory method, that is a method that creates instances of the class. In other words, class methods can serve as alternative constructors.

In our example code, an instance of Employee can be constructed by providing three arguments; first_name , last_name and salary.

employee_1 = Employee('Andrew', 'Brown', 85000)
print(employee_1.first_name)
print(employee_1.salary)

'Andrew'
85000

Now let’s assume that there’s a chance that the name of an Employee can be provided in a single field in which the first and last names are separated by a whitespace. In this case, we could possibly use our class method called employee_from_full_name that accepts three arguments in total. The first one, is the class itself, which is an implicit argument which means that it won’t be provided when calling the method — Python will automatically do this for us:

employee_2 = Employee.employee_from_full_name('John Black', 95000)
print(employee_2.first_name)
print(employee_2.salary)

'John'
95000

Note that it is also possible to call employee_from_full_name from object instances although in this context it doesn’t make a lot of sense:

employee_1 = Employee('Andrew', 'Brown', 85000)
employee_2 = employee_1.employee_from_full_name('John Black', 95000)

Another reason why we might want to create a class method, is when we need to change the state of the class. In our example, the class variable NO_OF_EMPLOYEES keeps track of the number of employees currently working for the company. This method is called every time a new instance of Employee is created and it updates the count accordingly:

employee_1 = Employee('Andrew', 'Brown', 85000)
print(f'Number of employees: {Employee.NO_OF_EMPLOYEES}')
employee_2 = Employee.employee_from_full_name('John Black', 95000)
print(f'Number of employees: {Employee.NO_OF_EMPLOYEES}')

Number of employees: 1
Number of employees: 2

Static methods

On the other hand, in static methods neither the instance (i.e. self) nor the class itself (i.e. cls) is passed as an implicit argument. This means that such methods, are not capable of accessing the class itself or its instances. Now one could argue that static methods are not useful in the context of classes as they can also be placed in helper modules instead of adding them as members of the class. In object oriented programming, it is important to structure your classes into logical chunks and thus, static methods are quite useful when we need to add a method under a class simply because it logically belongs to the class. In our example, the static method named get_employee_legal_obligations_txt simply returns a string that contains the legal obligations of every single employee of a company. This function, does not interact with the class itself nor with any instance. It could have been placed into a different helper module however, it is only relevant to this class and therefore we have to place it under the Employee class.

A static method can be access directly from the class itself

print(Employee.get_employee_legal_obligations_txt())


    1. An employee must complete 8 hours per working day
    2. ...

or from an instance of the class:

employee_1 = Employee('Andrew', 'Brown', 85000)
print(employee_1.get_employee_legal_obligations_txt())


    1. An employee must complete 8 hours per working day
    2. ...

References

Amiss answered 4/2, 2021 at 16:0 Comment(0)
P
2

One pretty important practical difference occurs when subclassing. If you don't mind, I'll hijack @unutbu's example:

class A: 
    def foo(self, x): 
        print("executing foo(%s, %s)" % (self, x)) 
 
    @classmethod
    def class_foo(cls, x): 
        print("executing class_foo(%s, %s)" % (cls, x))
 
    @staticmethod 
    def static_foo(x): 
        print("executing static_foo(%s)" % x)

class B(A):
    pass

In class_foo, the method knows which class it is called on:

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

In static_foo, there is no way to determine whether it is called on A or B:

A.static_foo(1)
# => executing static_foo(1)
B.static_foo(1)
# => executing static_foo(1)

Note that this doesn't mean you can't use other methods in a staticmethod, you just have to reference the class directly, which means subclasses' staticmethods will still reference the parent class:

class A:
    @classmethod
    def class_qux(cls, x):
        print(f"executing class_qux({cls}, {x})")
    
    @classmethod
    def class_bar(cls, x):
        cls.class_qux(x)

    @staticmethod
    def static_bar(x):
        A.class_qux(x)

class B(A):
    pass

A.class_bar(1)
# => executing class_qux(<class '__main__.A'>, 1)
B.class_bar(1)
# => executing class_qux(<class '__main__.B'>, 1)
A.static_bar(1)
# => executing class_qux(<class '__main__.A'>, 1)
B.static_bar(1)
# => executing class_qux(<class '__main__.A'>, 1)
Popliteal answered 31/7, 2020 at 18:12 Comment(0)
R
2

tldr;

A staticmethod is essentially a function bound to a class (and consequently its instances)

A classmethod is essentially an inheritable staticmethod.

For details, see the excellent answers by others.

Reese answered 3/2, 2021 at 3:32 Comment(0)
R
2

@classmethod is more powerful than @staticmethod.

@classmethod:

  • can call class variables and instance, class and static methods both by cls and directly by class name but not instance variables.

  • can be called both by object and directly by class name.

  • needs cls for the 1st argument otherwise @classmethod cannot be called and the name of cls is used in convention so other names instead of cls still work.

@staticmethod:

  • can be called both by an object and directly by class name.

  • can call class variables and instance, class and static methods directly by class name but not instance variables.

  • doesn't need self or cls.

*In detail, I also explain about instance method in my answer for What is an "instance method" in Python?

@classmethod:

For example, @classmethod can call the class variable and the instance, class and static methods both by cls and directly by class name and @classmethod can be called both by object and directly by class name as shown below:

class Person:
    x = "Hello"
    def __init__(self, name):
        self.name = name
    
    @classmethod # Here
    def test1(cls):
        print(cls.x)   # Class variable by `cls`
        cls.test2(cls) # Instance method by `cls`
        cls.test3()    # Class method by `cls`
        cls.test4()    # Static method by `cls`
        print()
        print(Person.x)       # Class variable by class name
        Person.test2("Test2") # Instance method by class name
        Person.test3()        # Class method by class name
        Person.test4()        # Static method by class name
    
    def test2(self):
        print("Test2")
        
    @classmethod
    def test3(cls):
        print("Test3")
        
    @staticmethod
    def test4():
        print("Test4")

obj = Person("John")
obj.test1() # By object

# Or

Person.test1() # By class name

Output:

Hello
Test2
Test3
Test4

Hello
Test2
Test3
Test4

And, @classmethod cannot call instance variables both by cls and directly by class name so if @classmethod tries to call the instance variable both by cls and directly by class name as shown below:

# ...
    
    @classmethod
    def test1(cls):
        print(cls.name) # Instance variable by `cls`
        
        # Or

        print(Person.name) # Instance variable by class name
# ...

obj = Person("John")
obj.test1()

# Or

Person.test1()

The error below occurs:

AttributeError: type object 'Person' has no attribute 'name'

And, if @classmethod doesn't have cls:

# ...
    
    @classmethod
    def test1(): # Without "cls"
        print("Test1")
  
# ...

obj = Person("John")
obj.test1()

# Or

Person.test1()

@classmethod cannot be called, then the error below occurs as shown below:

TypeError: test1() takes 0 positional arguments but 1 was given

And, the name of cls is used in convention so other name instead of cls still work as shown below:

# ...

    @classmethod
    def test1(orange):
        print(orange.x)      # Class variable
        orange.test2(orange) # Instance method
        orange.test3()       # Class method
        orange.test4()       # Static method

# ...

obj = Person("John")
obj.test1()

# Or

Person.test1()

Output:

Hello
Test2
Test3
Test4

@staticmethod:

For example, @staticmethod can be called both by object and directly by class name as shown below:

class Person:
    x = "Hello"
    def __init__(self, name):
        self.name = name

    @staticmethod # Here
    def test1():
        print("Test1")
    
    def test2(self):
        print("Test2")
        
    @classmethod
    def test3(cls):
        print("Test3")
        
    @staticmethod
    def test4():
        print("Test4")

obj = Person("John")
obj.test1() # By object

# Or

Person.test1() # By class name

Output:

Test1

And, @staticmethod can call the class variable and the instance, class and static methods directly by class name but not instance variable as shown below:

# ...
    
    @staticmethod
    def test1():
        print(Person.x)       # Class variable
        Person.test2("Test2") # Instance method
        Person.test3()        # Class method
        Person.test4()        # Static method
            
# ...

obj = Person("John")
obj.test1()

# Or

Person.test1()

Output:

Hello
Test2
Test3
Test4

And, if @staticmethod tries to call the instance variable as shown below:

# ...
    
    @staticmethod
    def test1():
        print(Person.name) # Instance variable
            
# ...

obj = Person("John")
obj.test1()

# Or

Person.test1()

The error below occurs:

AttributeError: type object 'Person' has no attribute 'name'

And, @staticmethod doesn't need self or cls so if @staticmethod has self or cls, you need to pass an argument as shown below:

# ...
    
    @staticmethod
    def test1(self): # With "self"
        print(self)

    # Or

    @staticmethod
    def test1(cls): # With "cls"
        print(cls)

# ...

obj = Person("John")
obj.test1("Test1") # With an argument

# Or

Person.test1("Test1") # With an argument

Output:

Test1

Otherwise, if you don't pass an argument as shown below:

# ...
    
    @staticmethod
    def test1(self): # With "self"
        print("Test1")

    # Or

    @staticmethod
    def test1(cls): # With "cls"
        print("Test1")

# ...

obj = Person("John")
obj.test1() # Without an argument

# Or

Person.test1() # Without an argument

These errors below occur:

TypeError: test1() missing 1 required positional argument: 'self'

TypeError: test1() missing 1 required positional argument: 'cls'

Recording answered 17/11, 2022 at 4:31 Comment(0)
C
1

There is no special upside of @staticmethod over @classmethod. If you're starting a codebase from scratch and want to lean towards simplicity and consistency, just stick with @classmethod.

If you don't trust me, what about the creator of Python?

Honestly, staticmethod was something of a mistake -- I was trying to do something like Java class methods but once it was released I found what was really needed was classmethod. But it was too late to get rid of staticmethod.

— Guido van Rossum, RE: Good uses for staticmethod

Celestine answered 17/5, 2023 at 8:33 Comment(0)
B
0

staticmethod has no access to attibutes of the object, of the class, or of parent classes in the inheritance hierarchy. It can be called at the class directly (without creating an object).

classmethod has no access to attributes of the object. It however can access attributes of the class and of parent classes in the inheritance hierarchy. It can be called at the class directly (without creating an object). If called at the object then it is the same as normal method which doesn't access self.<attribute(s)> and accesses self.__class__.<attribute(s)> only.

Think we have a class with b=2, we will create an object and re-set this to b=4 in it. Staticmethod cannot access nothing from previous. Classmethod can access .b==2 only, via cls.b. Normal method can access both: .b==4 via self.b and .b==2 via self.__class__.b.

We could follow the KISS style (keep it simple, stupid): Don't use staticmethods and classmethods, don't use classes without instantiating them, access only the object's attributes self.attribute(s). There are languages where the OOP is implemented that way and I think it is not bad idea. :)

Bumpkin answered 2/3, 2020 at 16:1 Comment(2)
One important thing more to classmethods: If you modify an attribute in the class method, all existing objects of this class which do not explicitly set this attribute will have the modified value.Bumpkin
the first sentence isn't quite true. a staticmethod can access public class members by specifying the class name, just as any caller couldTelecast
G
0

Definition of static method and class method from it's documentation. and When to use static method and when to use class method.

  • Static method are like static method in java and C#, it won't use any initialize value of the class, all it need from outside to work fine.

  • class method: are generally used for inheritance override, when we over-ride a method, and then we use CLS instance to tell if we want to call method of child or parent class. in case you want to use both the methods with same name and different signature.

staticmethod(function) -> method

Convert a function to be a static method.

A static method does not receive an implicit first argument.
To declare a static method, use this idiom:

     class C:
         @staticmethod
         def f(arg1, arg2, ...):
             ...

It can be called either on the class (e.g. C.f()) or on an instance
(e.g. C().f()).  The instance is ignored except for its class.

Static methods in Python are similar to those found in Java or C++.
For a more advanced concept, see the classmethod builtin.
"""

classmethod(function) -> method

Convert a function to be a class method.

A class method receives the class as implicit first argument,
just like an instance method receives the instance.
To declare a class method, use this idiom:

  class C:
      @classmethod
      def f(cls, arg1, arg2, ...):
          ...

It can be called either on the class (e.g. C.f()) or on an instance
(e.g. C().f()).  The instance is ignored except for its class.
If a class method is called for a derived class, the derived class
object is passed as the implied first argument.

Class methods are different than C++ or Java static methods.
If you want those, see the staticmethod builtin.
Globule answered 20/7, 2021 at 18:18 Comment(0)
S
0

I'd like to add on top of all the previous answers the following, which is not official, but adheres to standards.

First of all you can look at always giving the least amount of privilege necessary. So if you don't need something specific to the instance, make it a class method. If you don't need something specific to the class, make it a static method.

Second thing is consider what you can communicate by the type of method that you make it. Static Method - helper function meant to be used outside of the class itself. Class function - can be called without instantiation however is meant to be used with that class only - otherwise would've been a static method ! Instance method - meant to be used only by instances.

This can help you in communicating patterns and how your code should be used.

class Foo:
    @classmethod
    def bar(cls, id: int = None):
        query = session.query(
            a.id,
            a.name,
            a.address,
        )

        if id is not None:
            query = query.filter(a.id == id)

        return query

For example the above -- there is no reason why the method bar could not be static. However by making it a class method you communicate that it should be used by the class itself, as opposed it being a helper function meant to be used elsewhere !

Remember the above is not official, rather my personal preference

Staid answered 26/9, 2022 at 9:31 Comment(0)
D
-5

A quick hack-up ofotherwise identical methods in iPython reveals that @staticmethod yields marginal performance gains (in the nanoseconds), but otherwise it seems to serve no function. Also, any performance gains will probably be wiped out by the additional work of processing the method through staticmethod() during compilation (which happens prior to any code execution when you run a script).

For the sake of code readability I'd avoid @staticmethod unless your method will be used for loads of work, where the nanoseconds count.

Dunsany answered 17/12, 2012 at 18:51 Comment(1)
"Otherwise seems to serve no function": not strictly true. See above discussion.Wilds

© 2022 - 2024 — McMap. All rights reserved.