Python, когда использовать экземпляр против статических методов

Я пытаюсь понять, когда имеет смысл использовать метод экземпляра вместо статического метода. Кроме того, я не знаю, являются ли мои функции статичными, поскольку нет декоратора @staticmethod. Смогу ли я получить доступ к функциям класса, когда я вызову один из методов?

Я работаю над веб-браузером, который отправляет информацию в базу данных. Он запускается раз в неделю. Структура моего кода выглядит следующим образом

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

Это основная структура. Код функционален, но я не знаю, правильно ли я использую методы (функции?), И, возможно, упускаю способы использовать мой код в будущем. Я даже могу писать плохой код, который приведет к ошибкам, которые невозможно отладить только потому, что я не следовал рекомендациям.

После прочтения о том, когда используются методы класса и экземпляра. Я не понимаю, почему я бы их использовал. Если я хочу, чтобы URL был построен или данные были получены с веб-сайта, я вызываю функцию build_url или get_web_data. Мне не нужен экземпляр функции для отслеживания чего-либо отдельного. Я не могу себе представить, когда мне нужно будет разделить что-либо, что, я думаю, является частью проблемы.

Причина, по которой я думаю, что мой вопрос отличается от предыдущих, заключается в следующем: концептуальные примеры, объясняющие различия, не помогают мне, когда я сижу и пишу код. Я не сталкивался с реальными проблемами, которые решаются с помощью различных методов, которые показывают, когда мне следует даже использовать метод экземпляра, но методы экземпляра кажутся обязательными при рассмотрении концептуальных примеров кода.

Спасибо!

4 ответа

Решение

Функции, которые вы написали в своем коде, являются методами экземпляра, но они были написаны неправильно. Метод экземпляра должен иметь self как первый параметр

т.е. def build_url(self, url_paramater1, url_parameter2, request_date):

Тогда ты называешь это так

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

это self Параметр предоставляется Python и позволяет вам получить доступ ко всем свойствам и функциям - статическим или нет - вашего Get учебный класс.

Если вам не нужен доступ к другим функциям или свойствам в вашей функции, тогда вы добавляете @staticmethod декоратор и удалить self параметр

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

И тогда вы можете позвонить прямо

Get.build_url(url_paramater1, url_parameter2, request_date)

или позвоните из экземпляра класса

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

Но что за проблема с вашим текущим кодом вы можете спросить? Попробуйте вызвать его из такого экземпляра, и вы увидите проблему

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

Пример, в котором полезно создать экземпляр: допустим, вы хотите создать чат-клиент.

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

Классы могут использоваться для представления объектов, а также для группировки функций в общем пространстве имен.

Когда класс представляет объект, например кошку, все, что этот объект "может делать", логически должно быть методом экземпляра, таким как мяуканье.

Но когда у вас есть группа статических функций, которые все связаны друг с другом или обычно используются вместе для достижения общей цели, например build_url а также web_dataВы можете сделать свой код более понятным и организованным, поместив их в статический класс, который, как и вы, обеспечивает общее пространство имен.

Поэтому, на мой взгляд, структура, которую вы выбрали, является законной. Однако стоит учесть, что статические классы вы найдете больше в более определенно ООП-языках, таких как Java, в то время как в Python чаще используются модули для разделения пространства имен.

Этот код не должен быть классом вообще. Это должна быть просто пара функций. Вы не можете понять, зачем вам нужен метод экземпляра, потому что у вас нет причины создавать объект в первую очередь.

Из приведенного примера, нет необходимости иметь Get класс в конце концов, так как вы используете его как дополнительное пространство имен. У вас нет никакого "состояния", которое вы хотите сохранить ни в классе, ни в экземпляре класса.

То, что кажется хорошим, - это иметь отдельный модуль и определять в нем эти функции. Таким образом, при импорте этого модуля вы получаете желаемое пространство имен.

Другие вопросы по тегам