To call a static method in class use a static method from within the body of the class, and define the static method using the built-in staticmethod function as a decorator in Python.
The static method works similarly to a function in a Python script, but it is located within the class body. A static method can be called from either a class or object reference. We can call it Utils if foo() is a static function in Class Utils. Utils.
Python Static Method vs Instance Method We require the “self variable” as the formal parameter for the instance method. There is no such restriction with the static method. We use @staticmethod decorator to create a static method.
A static method (or static function) is a method defined as a member of an object but is accessible directly from an API object's constructor, rather than from an object instance created via the constructor.
staticmethod
objects apparently have a __func__
attribute storing the original raw function (makes sense that they had to). So this will work:
class Klass(object):
@staticmethod # use as decorator
def stat_func():
return 42
_ANS = stat_func.__func__() # call the staticmethod
def method(self):
ret = Klass.stat_func()
return ret
As an aside, though I suspected that a staticmethod object had some sort of attribute storing the original function, I had no idea of the specifics. In the spirit of teaching someone to fish rather than giving them a fish, this is what I did to investigate and find that out (a C&P from my Python session):
>>> class Foo(object):
... @staticmethod
... def foo():
... return 3
... global z
... z = foo
>>> z
<staticmethod object at 0x0000000002E40558>
>>> Foo.foo
<function foo at 0x0000000002E3CBA8>
>>> dir(z)
['__class__', '__delattr__', '__doc__', '__format__', '__func__', '__get__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
>>> z.__func__
<function foo at 0x0000000002E3CBA8>
Similar sorts of digging in an interactive session (dir
is very helpful) can often solve these sorts of question very quickly.
This is the way I prefer:
class Klass(object):
@staticmethod
def stat_func():
return 42
_ANS = stat_func.__func__()
def method(self):
return self.__class__.stat_func() + self.__class__._ANS
I prefer this solution to Klass.stat_func
, because of the DRY principle.
Reminds me of the reason why there is a new super()
in Python 3 :)
But I agree with the others, usually the best choice is to define a module level function.
For instance with @staticmethod
function, the recursion might not look very good (You would need to break DRY principle by calling Klass.stat_func
inside Klass.stat_func
). That's because you don't have reference to self
inside static method.
With module level function, everything will look OK.
What about injecting the class attribute after the class definition?
class Klass(object):
@staticmethod # use as decorator
def stat_func():
return 42
def method(self):
ret = Klass.stat_func()
return ret
Klass._ANS = Klass.stat_func() # inject the class attribute with static method value
This is due to staticmethod being a descriptor and requires a class-level attribute fetch to exercise the descriptor protocol and get the true callable.
From the source code:
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.
But not directly from inside the class while it is being defined.
But as one commenter mentioned, this is not really a "Pythonic" design at all. Just use a module level function instead.
What about this solution? It does not rely on knowledge of @staticmethod
decorator implementation. Inner class StaticMethod plays as a container of static initialization functions.
class Klass(object):
class StaticMethod:
@staticmethod # use as decorator
def _stat_func():
return 42
_ANS = StaticMethod._stat_func() # call the staticmethod
def method(self):
ret = self.StaticMethod._stat_func() + Klass._ANS
return ret
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With