首页 > 解决方案 > 允许惰性 API 调用和两种构造的 Python 类

问题描述

我一直在做一个项目,为现有的 REST API 创建一个 python 模块。基本上,该 API 包括获取有关巴西官方地理位置的数据。

为简化起见,假设我们有类:RegionsRegionRegions负责从 API 中收集所有国家区域并生成Region对象列表。用户应该能够使用这两个类来获取信息。现在我对此有几个问题:

  1. 如果用户想Region直接使用为国家的特定区域创建对象,我应该如何将对象的创建限制为只允许存在的区域,避免对象代表不存在的区域?我是否应该每次都查询 API 以检查该区域是否存在?我应该只允许Regionid 为 1 到 5 的。

  2. 我想进行惰性 API 调用。也就是说,只有在该执行之前从未发生过调用时才会发生调用。这是最好的方法(下)吗?(不知道这是否是懒惰的定义,但这里的目标是尽量减少调用)。

  3. 当我RegionRegions类内部创建一个对象时,我已经拥有了创建每个Region. 但是如果用户Region直接实例化,我还没有拨打任何电话。我应该如何构建 Region 类以允许这两种方法?Region从类内部创建对象时,我不想再次调用 API 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]

标签: pythonapimodulepython-3.6

解决方案


我不鼓励用户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


推荐阅读