0

I would like to ask about usage of static methods inside other methods in python class. I don't know where should i post it, but meta.stackexchange recommended to post it here.

What i want to do is to build StringProcessor class, which should preprocess a string. I want to start with basic functionality(like deletion of bad characters, strip etc.) but later the plan is to extend basic functionality.

First variant of the class:

import re


class StringProcessor:
    """
    This class is responsible for the string preprocessing.
    """
    def __init__(self,bad_chars = None):
        self.bad_chars = bad_chars
            

    def link_processor(self,string):
        #preprocessing of the link
        return string


    def name_surname_processor(self,string):
        #manipulation with names and surnames

        return string

    def delete_bad_characters(self,string):
        if self.bad_chars is not None:
            return string.translate(self.bad_chars)
        return string
        

    def standard_processor(self,string):
        string = self.delete_bad_characters(string)
        string = self.link_processor(string)
        string = string.strip()
        string = string.lower()

        return string

So here I am stick to the instance methods.

Here is the second variant of the class:

class StringProcessor:
    """
    This class is responsible for the string preprocessing.
    """
    def __init__(self,bad_chars = None):
        self.bad_chars = bad_chars
            
    @staticmethod
    def link_processor(string):
        #preprocessing of the link
        return string

    @staticmethod
    def name_surname_processor(string):
        #preprocessing of the name and surname
        return string

        return string

    def delete_bad_characters(self,string):
        if self.bad_chars is not None:
            return string.translate(self.bad_chars)
        return string
        
    def standard_processor(self,string):
        string = self.delete_bad_characters(string)
        string = self.link_processor(string)
        string = string.strip()
        string = string.lower()

        return string

The idea is, that standard_processor() is a main method, which uses other helper methods(like link_processor) for the string preprocessing. My question is: in this case is it better to use @staticmethod for the helper methods of it's better to stick with regular instance methods?

James
  • 32,991
  • 4
  • 47
  • 70
Daniel Yefimov
  • 860
  • 1
  • 10
  • 24
  • Does this answer your question? [Why do we use @staticmethod?](https://stackoverflow.com/questions/23508248/why-do-we-use-staticmethod), https://stackoverflow.com/questions/7667667/how-to-use-static-helper-method-in-a-class, https://stackoverflow.com/questions/7855237/python-should-i-put-my-helper-functions-inside-or-outside-the-class – mkrieger1 Aug 09 '22 at 10:07

1 Answers1

1

It is a matter of preference. Adding static methods to a class simply adds that function to the class's namespace. It does have the benefit of being able to call the static method without having instantiated the class. I.e.:

class StringProcessor:
    """
    This class is responsible for the string preprocessing.
    """
    def __init__(self,bad_chars = None):
        self.bad_chars = bad_chars
            
    @staticmethod
    def drop_newlines(string):
        return re.sub(r'[\n\r]', '', string)


# not-instantiated
StringProcessor.drop_newlines('hello\nworld')
# returns:
'helloworld'

My preference is to not use static methods, and instead keep them as functions that are called within the class.

def drop_newlines(string):
    return re.sub(r'[\n\r]', '', string)

def reduce_white_space(string):
    return re.sub(r'[\t ]+', ' ', string)

class StringProcessor:
    """
    This class is responsible for the string preprocessing.
    """
    def __init__(self,bad_chars = None):
        self.bad_chars = bad_chars
            
    def clean_whitespace(self, string):
        out = drop_newlines(string)
        out = reduce_white_space(out)
        return out

However, as I was writing this, I noticed that we are calling re.sub. This is fine if it is used occasionally, but you can speed it up by compiling the regular expression first, and then calling .sub. But where to store the compiled regexes? Well, that is what attributes in classes are for!

So here is how I would probably write it:

class StringProcessor:
    """
    This class is responsible for the string preprocessing.
    """
    REGEX_NEWLINE = re.compile(r'[\n\r]')
    REGEX_WHITESPACE = re.compile(r'[\t ]+')

    def __init__(self,bad_chars = None):
        self.bad_chars = bad_chars

    def drop_newlines(self, string):
        return self.REGEX_NEWLINE.sub('', string)

    def reduce_white_space(self, string):
        return self.REGEX_WHITESPACE.sub(' ', string)
            
    def clean_whitespace(self, string):
        out = self.drop_newlines(string)
        out = self.reduce_white_space(out)
        return out

But again, just my opinion.

James
  • 32,991
  • 4
  • 47
  • 70