Categories
python static-methods

Static methods in Python?

1929

Can I define a static method which I can call directly on the class instance? e.g.,

MyClass.the_static_method()

0

    2199

    Yep, using the staticmethod decorator:

    class MyClass(object):
        @staticmethod
        def the_static_method(x):
            print(x)
    
    MyClass.the_static_method(2)  # outputs 2
    

    Note that some code might use the old method of defining a static method, using staticmethod as a function rather than a decorator. This should only be used if you have to support ancient versions of Python (2.2 and 2.3):

    class MyClass(object):
        def the_static_method(x):
            print(x)
        the_static_method = staticmethod(the_static_method)
    
    MyClass.the_static_method(2)  # outputs 2
    

    This is entirely identical to the first example (using @staticmethod), just not using the nice decorator syntax.

    Finally, use staticmethod sparingly! There are very few situations where static-methods are necessary in Python, and I’ve seen them used many times where a separate “top-level” function would have been clearer.


    The following is verbatim from the documentation::

    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().

    For more information on static methods, consult the documentation on the standard type hierarchy in The standard type hierarchy.

    New in version 2.2.

    Changed in version 2.4: Function decorator syntax added.

    6

    • 26

      Why adding @staticmethod decoration or using a function pointer, when you can simply avoid the first self parameter? Well, for an object a, you won’t be able to call a.your_static_method(), which is allowed in other languages, but it is anyway considered a bad practice and the compiler always warns about it

      May 22, 2017 at 15:40


    • 1

      I am using python 2.7.12, with @staticmethod decorator I am unable to call first static method defined. Its givin error : TypeError: ‘staticmethod’ object is not callable

      Jul 23, 2017 at 8:07

    • 24

      @SomethingSomething, if you don’t use the variable name “self”, but do not add the decorator, the first argument eg arg1 will still be the reference to the self instance. The name self is only a convention.

      Aug 29, 2018 at 9:09

    • 2

      @GeorgeMoutsopoulos – agreed generally. But – you will anyway be able to call the method as ClassName.methodName(), as if it was a static one, and then no selfwill be provided to the method. As you said, it will still be possible to also call this method as ClassInstance.methodName(), and self will be provided as the first parameter, regardless of its name.

      Aug 29, 2018 at 10:30


    • 1

      @SomethingSomething so many SO answers, blog posts, and references and NO ONE seems to answer this question. I completely agree with everything you said. One should neither write self.staticMethod() nor instance.staticMethod(). The only exception I found is when you use inheritance and want the staticMethod to be overridden, which seems to work in Python. Now calling self.staticMethod() acknowledges the class type of self… This might be interesting with factory methods or clones when needed within the class but is probably still rare

      – IceFire

      Jul 10, 2020 at 6:03

    245

    I think that Steven is actually right. To answer the original question, then, in order to set up a class method, simply assume that the first argument is not going to be a calling instance, and then make sure that you only call the method from the class.

    (Note that this answer refers to Python 3.x. In Python 2.x you’ll get a TypeError for calling the method on the class itself.)

    For example:

    class Dog:
        count = 0 # this is a class variable
        dogs = [] # this is a class variable
    
        def __init__(self, name):
            self.name = name #self.name is an instance variable
            Dog.count += 1
            Dog.dogs.append(name)
    
        def bark(self, n): # this is an instance method
            print("{} says: {}".format(self.name, "woof! " * n))
    
        def rollCall(n): #this is implicitly a class method (see comments below)
            print("There are {} dogs.".format(Dog.count))
            if n >= len(Dog.dogs) or n < 0:
                print("They are:")
                for dog in Dog.dogs:
                    print("  {}".format(dog))
            else:
                print("The dog indexed at {} is {}.".format(n, Dog.dogs[n]))
    
    fido = Dog("Fido")
    fido.bark(3)
    Dog.rollCall(-1)
    rex = Dog("Rex")
    Dog.rollCall(0)
    

    In this code, the “rollCall” method assumes that the first argument is not an instance (as it would be if it were called by an instance instead of a class). As long as “rollCall” is called from the class rather than an instance, the code will work fine. If we try to call “rollCall” from an instance, e.g.:

    rex.rollCall(-1)
    

    however, it would cause an exception to be raised because it would send two arguments: itself and -1, and “rollCall” is only defined to accept one argument.

    Incidentally, rex.rollCall() would send the correct number of arguments, but would also cause an exception to be raised because now n would be representing a Dog instance (i.e., rex) when the function expects n to be numerical.

    This is where the decoration comes in:
    If we precede the “rollCall” method with

    @staticmethod
    

    then, by explicitly stating that the method is static, we can even call it from an instance. Now,

    rex.rollCall(-1)
    

    would work. The insertion of @staticmethod before a method definition, then, stops an instance from sending itself as an argument.

    You can verify this by trying the following code with and without the @staticmethod line commented out.

    class Dog:
        count = 0 # this is a class variable
        dogs = [] # this is a class variable
    
        def __init__(self, name):
            self.name = name #self.name is an instance variable
            Dog.count += 1
            Dog.dogs.append(name)
    
        def bark(self, n): # this is an instance method
            print("{} says: {}".format(self.name, "woof! " * n))
    
        @staticmethod
        def rollCall(n):
            print("There are {} dogs.".format(Dog.count))
            if n >= len(Dog.dogs) or n < 0:
                print("They are:")
                for dog in Dog.dogs:
                    print("  {}".format(dog))
            else:
                print("The dog indexed at {} is {}.".format(n, Dog.dogs[n]))
    
    
    fido = Dog("Fido")
    fido.bark(3)
    Dog.rollCall(-1)
    rex = Dog("Rex")
    Dog.rollCall(0)
    rex.rollCall(-1)
    

    3

    • 8

      The first example (calling by class without @staticmethod) doesn’t work for me on Python 2.7. I get “TypeError: unbound method rollCall() must be called with Dog instance as first argument (got int instance instead)”

      – tba

      Feb 21, 2013 at 21:46


    • 2

      This does not work. Both Dog.rollCall(-1) and rex.rollCall(-1) return the same TypeError: unbound method rollCall() must be called with Dog instance as first argument (got int instance instead)

      Oct 14, 2013 at 14:26

    • 5

      @MestreLion I think this is not a huge benefit, since all it does is muddle up static and instance methods and make one look like the other. If you know a method is static, you should access it as a static method. The fact that the method does not need or use your instance should be self-evident wherever you use the method. I always use T.my_static_method() or type(my_t_instance).my_static_method(), since this is clearer and makes it immediately obvious that I’m calling a static method.

      Nov 15, 2014 at 1:07

    90

    Yes, check out the staticmethod decorator:

    >>> class C:
    ...     @staticmethod
    ...     def hello():
    ...             print "Hello World"
    ...
    >>> C.hello()
    Hello World
    

    1

    • 1

      Many answer above were downvoted because they provide just an example. Why this is different?

      – Gigino

      Dec 10, 2020 at 8:25