67

I am curious about why we need the @staticmethod decorator to declare method as static.

I was reading about static methods in Python, and I came to know that a static method can be callable without instantiating its class.

So I tried the two examples below, but both do the same:

class StatMethod:
  def stat():
    print("without Decorator")

class StatMethod_with_decorator:
  @staticmethod
  def stat():
    print("With Decorator")

If I call the stat() method on the class directly, both print/show the values below:

>> StatMethod.stat()
without Decorator
>> StatMethod_with_decorator.stat()
With Decorator
ivanleoncz
  • 9,070
  • 7
  • 57
  • 49
Sanjay
  • 1,958
  • 2
  • 17
  • 25
  • 1
    Now try it with a function that takes some arguments... – PM 2Ring Apr 24 '17 at 11:43
  • 2
    This might help: http://stackoverflow.com/questions/136097/what-is-the-difference-between-staticmethod-and-classmethod-in-python – Kendas Apr 24 '17 at 11:44
  • 1
    Note that I've found out with some tests that Python 2.7 requires using the decorator when the function has an arg, whereas Python 3 does not. Python 2.7 tries to match the first arg to the instance (it thinks it's self), whereas Python 3 seems to understand that one arg is just the function's arg, without having to use the annotation for that. I haven't found anything about this specific difference in the docs. – JRobinss Dec 05 '18 at 15:41

5 Answers5

99

You need the decorator if you intend to try to call the @staticmethod from the instance of the class instead of of the class directly

class Foo():
    def bar(x):
        return x + 5

>>> f = Foo()
>>> f.bar(4)
Traceback (most recent call last):
  File "<pyshell#7>", line 1, in <module>
    f.bar(4)
TypeError: bar() takes 1 positional argument but 2 were given

Now if I declare @staticmethod the self argument isn't passed implicitly as the first argument

class Foo():
    @staticmethod
    def bar(x):
        return x + 5

>>> f = Foo()
>>> f.bar(4)
9
Cory Kramer
  • 114,268
  • 16
  • 167
  • 218
  • Do you know if there is an established or agreed-upon term to refer to static methods that you can _only_ invoke through the class name directly? Or does the community simply call both "static methods"? Any connection to perhaps how these terms are used in Java, C# or elsewhere? Also, what would you say is their primary purpose vs static methods defined with the decorator? – Amelio Vazquez-Reina Apr 30 '20 at 01:19
  • So, when we only would use the method via the class and not via an instance object, then @staticmethod is optional? – IceFire Jul 10 '20 at 05:32
  • This is a good answer but the use of *foo* and *bar* makes this unnecessarily hard to understand. Descriptive variables help in examples, too. Not just production code. – problemofficer - n.f. Monica Dec 10 '21 at 10:04
  • @problemofficer-n.f.Monica I get your point but fwiw those are canonically the placeholder class/function/variable names when providing examples. In this case I think it does not detract from the point I am trying to make in my answer in any meaningful way. – Cory Kramer Dec 10 '21 at 11:53
  • *Foo* has semantics attached to it, it is a class. *bar* has semantics attached to it, it is a method of that class. I disagree that it is "canonical" because that term implies an authority or best-practice consensus. *Foo* and *bar* IMHO are merely remnants of an older age, where people did not understand the importance of descriptive variables. I heard your argument several times and think this is a [Appeal to tradition logical fallacy](https://en.wikipedia.org/wiki/Appeal_to_tradition) – problemofficer - n.f. Monica Dec 10 '21 at 12:02
  • Python... Oh Python... Yet another example of the mess it is – alelom Oct 26 '22 at 15:13
2

The documentation describes some transformations that are done when calling a user defined method:

Note that the transformation from function object to (unbound or bound) method object happens each time the attribute is retrieved from the class or instance. In some cases, a fruitful optimization is to assign the attribute to a local variable and call that local variable. Also notice that this transformation only happens for user-defined functions; other callable objects (and all non-callable objects) are retrieved without transformation. It is also important to note that user-defined functions which are attributes of a class instance are not converted to bound methods; this only happens when the function is an attribute of the class.

For methods marked as staticmethod this is different:

Static method objects provide a way of defeating the transformation of function objects to method objects described above. A static method object is a wrapper around any other object, usually a user-defined method object. When a static method object is retrieved from a class or a class instance, the object actually returned is the wrapped object, which is not subject to any further transformation. Static method objects are not themselves callable, although the objects they wrap usually are. Static method objects are created by the built-in staticmethod() constructor.

Flurin
  • 681
  • 5
  • 14
0

if function has some parameters, then call non static method would be failed

and static method didn't use the local variables in the class, but the class method will be

Jimmy Guo
  • 1,288
  • 1
  • 9
  • 24
-1

Update: In python 3.10 you dont need the decorator any more

Antonio
  • 3
  • 2
  • But i got same error with below code in python 3.10 in second print statement using an instance `class test(): def func(arg1, arg2): print('func') print(test.func(5, 'arg2')) s = test() print(s.func(5, 'arg2'))` – sjd May 04 '22 at 13:36
-3

Just my simple approach here. Forget the decorators. Use the class directly (Python 3.8):

class MyClass:
    def myMethod(self, myValue):
        print(myValue)

MyClass.myMethod(None, "hi")

Or both:

MyClass.myMethod(None, "hi from class")
myInstance = myClass()
myInstance.myMethod2("hi from instance")
Axel
  • 35
  • 1
  • 5
  • 3
    I would consider it an anti-pattern to accept an argument to a method if you do not intend to use it. So in this case accepting `self` but not using it falls into that category. It would therefore be canonical to make that method static. – Cory Kramer Jul 23 '20 at 18:15