dissidia
dissidia

Reputation: 1581

When to know to convert a method into a static method

I have 2 files that run together, a ui file and a util file.

This is the UI file:

import util
class MainWindow(object):
    ...
    def method_context_callback(self, *args):
        if args[0] == 'M1':
            self.ctx = utils.M1Context(...)
            self.ctx.run_context()
        elif args[1] == 'M2':
            self.ctx = utils.M2Context(...)
            self.ctx.run_context()

This is the Util file:

class M1Context(object):
    def __init__(self):
        ...
    def run_context(self):
        # Do something when Method01 is used

class M2Context(object):
    def __init__(self):
        ...
    def run_context(self):
        # Do something when Method02 is used

Is there a need to make run_context methods in the utils.py as a staticmethod? In my UI, there are 2 buttons, one each for Method01 and Method02, where User can use the buttons anytime he/she liked while the UI is being active.

I asked this because while I was reading something online, it was mentioned that it can be considered. To be honest, I am not very familiar with @staticmethod as generally I wrote my code in this format.

How do I know when and in what sort of situations should I make it as a static method?

Upvotes: 1

Views: 2202

Answers (3)

Menglong Li
Menglong Li

Reputation: 2255

There's no strict boundary about whether to use static method or not.

Regardless of the differences between the ways being called as a static method and a class method (you could save memory and be fast using static method cause you don't have to bind this method to a specific class instance).

Here I'll talk more about design patterns.

Ideally, static method means this function should be stateless, which declares that it should just act like a function, when passing same input each time, we got the same output. There's no inner state captured by the instance that can affect the logic and result of the static method.

So that's why in strategy design pattern, the strategy class usually be implemented as a so-called static class with a bunch of static methods.

As for your case, let's consider it in the following ways:

  • If you treat it like context, for context, as the name shows, each context should contain inner values and state. So static method here is not proper.
  • If you treat it like two different strategies, you should use static method.
  • So which is better: I suggest you combine the two design patterns together: use strategy to handle different logics, and use a new class called context to hold inner state and values to provide materials for strategy. Furthermore, your M1, M2 class should also have a base class, which can take the advantage of object oriented design.
from abc import ABCMeta, abstractmethod


class ContextBase(object):
    __metaclass__ = ABCMeta

    def __init__(self):
        pass

    @abstractmethod
    def run_context(self):
        print 'this is logic inside of base'

    @staticmethod
    def step_a():
        pass

    @staticmethod
    def step_b():
        pass

class M1Context(ContextBase):
    def __init__(self):
        super(M1Context, self).__init__()

    def run_context(self):
        super(M1Context, self).run_context()
        print 'logic inside of subclass'
        super(M1Context, self).step_a()
        super(M1Context, self).step_b()


m1 = M1Context()
m1.run_context()

Upvotes: 1

Paulo Scardine
Paulo Scardine

Reputation: 77251

My personal rules are:

  1. if I have a method that is starting to get too long or harder to read, I will try to refactor it into smaller chunks. I may try to create a few other methods and split the logic among them. If any of them make no use of self but make sense outside the object, I will turn it into a function, otherwise I will keep it as a method and apply the @static_method decorator.

  2. in the rare occasions where a method should be called from the class, I will make it a class method: for example when I have something like MyClass.create_new_instance_from_json(json_string).

Upvotes: 1

Nether
Nether

Reputation: 1160

A static method allows you to use it without a class instance. A side effect of that is that the static method cannot use anything attached to self.

class Banana:
    def __init__(self, age):
        self.age = age

    @staticmethod
    def get_calories():
        return 88.7

    def get_age():
        return self.age;

Banana.get_calories()  # Is valid
Banana.get_age()  # will not be valid

banana = Banana(age=2)
banana.get_age()  # valid
banana.get_calories() # valid

As far as I'm aware it's not good practice to mix in static methods and normal ones in a single class, but there are situations where it might make sense.

Upvotes: 1

Related Questions