Python класс, который допускает ленивые вызовы API и два типа построения - PullRequest
0 голосов
/ 30 марта 2020

Я работал над проектом по созданию модуля python для существующего REST API. В основном API заключается в получении данных об официальных географических c точках в Бразилии.

Для упрощения предположим, что у нас есть классы: Regions и Region. Regions отвечает за сбор всех регионов страны из API и создание списка Region объектов. Пользователь должен иметь возможность использовать оба класса для получения информации. Теперь у меня есть несколько вопросов по этому поводу:

  1. Если пользователь хочет использовать Region напрямую для создания объекта для определенного c региона страны, как я должен ограничивать создание объекта, разрешающего только существующие регионы, избегая объекта, представляющего регион, который не существует? Должен ли я обращаться к API каждый раз, чтобы проверить, существует ли регион? Я должен только разрешить Region с идентификатором от 1 до 5.

  2. Я хотел бы делать ленивые вызовы API. То есть вызов произойдет только в том случае, если он никогда не происходил ранее в этом исполнении. Это лучший подход (ниже)? (Не знаю, если это определение ленивых, но цель здесь состоит в том, чтобы минимизировать вызовы).

  3. Когда я создаю Region объект из класса Regions, У меня уже есть вся информация, необходимая для создания каждого Region. Но если пользователь установит Region напрямую, я еще не звонил. Как мне построить класс Region, чтобы учесть эти два подхода? Я не хочу снова вызывать API при создании объекта Region из класса Regions.

Упрощенный код приведен ниже:

class Region():
    def __init__(self, id_=None, code=None, name=None):
        self.id = id_
        self.code = code
        self.name = name

    def __repr__(self):
        return f"Region(id_={self.id}, name=\"{self.name}\", code=\"{self.code}\")"


class Regions():
    def __init__(self):
        self.__ran_once = False
        self.result = None
        self.content = None
        self.json = None

    def __get(self):
        self.json = HttpClient.get("regioes")

        self.content = []
        for obj in self.json:
            self.content.append(
                Region(obj["id"], obj["sigla"], obj["nome"])
            )

    def all(self, format_json=False):
        if not self.__ran_once:
            self.__get()
            self.__ran_once = True

        if format_json:
            return self.json

        return self.content

    def names(self):
        if not self.__ran_once:
            self.__get()
            self.__ran_once = True

        return [r.name for r in self.content]

1 Ответ

0 голосов
/ 30 марта 2020

Я бы не рекомендовал пользователю создавать экземпляры Region напрямую. Если они это сделают, это на свой страх и риск. Вы можете поместить это в строку документации.

То, что вы описываете, - это кэширование, а не лень. Я бы написал класс Regions так:

from cached_property import cached_property


class Regions:
    @cached_property
    def json(self):
        return HttpClient.get("regioes")

    @cached_property
    def content(self):
        return [
            Region(obj["id"], obj["sigla"], obj["nome"])
            for obj in self.json
        ]

    @cached_property
    def names(self):
        return [r["name"] for r in self.json]

Установить cached_property с pip install cached-property.

...