Daniel Butler
Daniel Butler

Reputation: 3736

Python when to use instance vs static methods

I am struggling to understand when it makes sense to use an instance method versus a static method. Also, I don't know if my functions are static since there is not a @staticmethod decorator. Would I be able to access the class functions when I make a call to one of the methods?

I am working on a webscraper that sends information to a database. It’s setup to run once a week. The structure of my code looks like this

import libraries...
class Get:
    def build_url(url_paramater1, url_parameter2, request_date):
        return url_with_parameters

    def web_data(request_date, url_parameter1, url_parameter2): #no use of self
        # using parameters pull the variables to look up in the database
        for a in db_info:
            url = build_url(a, url_parameter2, request_date)
            x = requests.Session().get(url, proxies).json()
            #save data to the database
        return None

    #same type of function for pulling the web data from the database and parsing it

if __name__ == ‘__main__’:
    Get.web_data(request_date, url_parameter1, url_parameter2)
    Parse.web_data(get_date, parameter) #to illustrate the second part of the scrapper

That is the basic structure. The code is functional but I don’t know if I am using the methods (functions?) correctly and potentially missing out on ways to use my code in the future. I may even be writing bad code that will cause errors down the line that are impossibly hard to debug only because I didn’t follow best practices.

After reading about when class and instance methods are used. I cannot see why I would use them. If I want the url built or the data pulled from the website I call the build_url or get_web_data function. I don’t need an instance of the function to keep track of anything separate. I cannot imagine when I would need to keep something separate either which I think is part of the problem.

The reason I think my question is different than the previous questions is: the conceptual examples to explain the differences don't seem to help me when I am sitting down and writing code. I have not run into real world problems that are solved with the different methods that show when I should even use an instance method, yet instance methods seem to be mandatory when looking at conceptual examples of code.

Thank you!

Upvotes: 2

Views: 2252

Answers (4)

Ramast
Ramast

Reputation: 7709

The functions you have wrote in your code are instance methods but they were written incorrectly. An instance method must have self as first parameter

i.e def build_url(self, url_paramater1, url_parameter2, request_date):

Then you call it like that

get_inst = Get()
get_inst.build_url(url_paramater1, url_parameter2, request_date)

This self parameter is provided by python and it allow you to access all properties and functions - static or not - of your Get class.

If you don't need to access other functions or properties in your class then you add @staticmethod decorator and remove self parameter

@staticmethod
def build_url(url_paramater1, url_parameter2, request_date):

And then you can call it directly

Get.build_url(url_paramater1, url_parameter2, request_date)

or call from from class instance

get_inst = Get()
get_inst.build_url(url_paramater1, url_parameter2, request_date)

But what is the problem with your current code you might ask? Try calling it from an instance like this and u will see the problem

get_inst = Get()
get_inst.build_url(url_paramater1, url_parameter2, request_date)

Example where creating an instance is useful: Let's say you want to make a chat client.

You could write code like this

class Chat:
    def send(server_url, message):
        connection = connect(server_url)
        connection.write(message)
        connection.close()

    def read(server_url):
        connection = connect(server_url)
        message = connection.read()
        connection.close()
        return message

But a much cleaner and better way to do it:

class Chat:

    def __init__(server_url):
        # Initialize connection only once when instance is created
        self.connection = connect(server_url)

    def __del__()
        # Close connection only once when instance is deleted
        self.connection.close()

    def send(self, message):
        self.connection.write(message)

    def read(self):
        return self.connection.read()

To use that last class you do

# Create new instance and pass server_url as argument
chat = Chat("http://example.com/chat")
chat.send("Hello")
chat.read()
# deleting chat causes __del__ function to be called and connection be closed
delete chat

Upvotes: 3

kmaork
kmaork

Reputation: 6012

Classes can be used to represent objects, and also to group functions under a common namespace.

When a class represents an object, like a cat, anything that this object 'can do', logically, should be an instance method, such as meowing.

But when you have a group of static functions that are all related to each other or are usually used together to achieve a common goal, like build_url and web_data, you can make your code clearer and more organized by putting them under a static class, which provides a common namespace, like you did.

Therefore in my opinion the structure you chose is legitimate. It is worth considering though, that you'd find static classes more in more definitively OOP languages, like Java, while in python it is more common to use modules for namespace separation.

Upvotes: 3

Ilija
Ilija

Reputation: 1604

From given example, there is no need to have Get class after all, since you are using it just like a additional namespace. You do not have any 'state' that you want to preserve, in either class or class instance.

What seems like a good thing is to have separate module and define these functions in it. This way, when importing this module, you get to have this namespace that you want.

Upvotes: 1

Ned Batchelder
Ned Batchelder

Reputation: 375584

This code doesn't need to be a class at all. It should just be a pair of functions. You can't see why you would need an instance method because you don't have a reason to instantiate the object in the first place.

Upvotes: 2

Related Questions