I have a beginner question about the decorator @staticmethod. In docummentation (for Python, v. 3.10 [it is an added line for this version]), I read: “Moreover, they can be called as regular functions (such as f() ).”
Does it mean that this should work? It seems that it should not (because it doesn’t work).
class C:
@staticmethod
def f():
print("Hi!")
f()
Does it mean that this ability is limited only to the scope of the class?
In the docummentation, there is also information about all decorators being callable as a regular function in this way:
def regular_function():
...
class C:
method = staticmethod(regular_function)
That is confusing… What is the special ability of @staticmethod to be called as regular function then (there is no such line in section of @classmethod)?
You still need to access the method as C.f. “Outside of class scope” is a confusing way to describe it.
The special behavior is that the static method is just a function, and does not have any special parameter special binding behavior like class methods and instance methods.
Also, to note, if you’re using a @staticmethod, its generally simpler and more Python to simply make it a regular function instead, since its simpler and more Pythonic, and otherwise no different from a practical perspective—@staticmethod is mostly included as a convenience for those used to that pattern from other, strictly OOP language (cough, Java, cough).
What the documentation means is that the static method can be used as a function inside the class, like this:
class C:
@staticmethod
def f():
return "Hello world"
# Okay to call f() inside the class.
attribute = f()
assert C.attribute == "Hello world"
Until Python 3.10, that would not work, as staticmethods were not directly callable unless they were accessed through the class C or an instance. But in Python 3.10, they were enhanced to be callable directly, so now all of these do the same thing:
# Access through the class.
C.f()
# Access through an instance.
obj = C()
obj.f()
# Bypass dot access and call the raw staticmethod.
raw_obj = vars(C)['f']
raw_obj()
In Python 3.9 and older, only the first two calls would work, not the third.