How to use self parameter, @staticmethod keyword inside a class and its methods

Stateless picture Stateless · May 30, 2017 · Viewed 19.2k times · Source

I have a python class which has multiple methods. I have defined my methods via @staticmethod instance and I want to call other methods of my class from inside my main function(main_function). I think I need self parameter for calling my other functions from my main function and I want to pass this parameter to my main_function when I create an instance of my class.

class myclass:
  @staticmethod
  def function1(param1)
      print "function1"
  @staticmethod
  def main_function(self, param1)
     function1(param1)

my_object = myclass()
my_object.main_function(param1)

I got this error:

TypeError: main_function() takes exactly 2 arguments (1 given)

The problem is that I have not self parameter when I create my instance. I tried to remove @staticmethod keyword from my method definition and remove all self parameter using, but this does not work.

Answer

Martijn Pieters picture Martijn Pieters · May 30, 2017

Only use @staticmethod if you are creating a function that you'd normally want to tie to specific classes but do not need any other context. For example, the str.maketrans() function is a static method because it is a utility function you'd often use when working with strings, namespacing it to the already-existing str type (which pre-exists as a class) makes sense there.

You appear to be using classes as a namespace instead. Don't do that. Use a module for your functions, and you don't have to worry about the special scoping rules that apply to classes. Only use a class when you need to bundle state with functionality.

If you insist on using classes with static methods anyway, you are stuck with hardcoding the class name everywhere:

class myclass:
    @staticmethod
    def function1(param1)
        print "function1"

    @staticmethod
    def main_function(param1)
        # Want to use other functions in this class? Then you will
        # have to use the full name of the class as a prefix:
        myclass.function1(param1)

You could make use of classmethods instead so you have a reference to the class object:

class myclass:
    @staticmethod
    def function1(param1)
        print "function1"

    @classmethod
    def main_function(cls, param1)
        # Now you can use the `cls` reference to access other attributes
        cls.function1(param1)

This has the added advantage that you can use inheritance.

However, using a module is the correct way to organise a set of functions into a namespace. Put everything into a my_module.py file in your package, and use importing;

import my_module

my_module.main_function(param1)

Now all globals in my_module are bundled into one module object, and no prefixing or cls references are needed.