首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python调用结构

Python调用结构
EN

Code Review用户
提问于 2023-05-02 19:19:49
回答 1查看 64关注 0票数 0

我正在为Starburst编写一个python库,并试图找到构建代码的最佳方法,这样代码就很枯燥,但也很容易理解。下面是一个不枯燥的代码示例。

我研究过的其他方法是使用不同的API调用拥有一个配置文件,并有一个用于get/put/delete/post的函数。

另一种方法是基于域进行分组,并将方法作为变量传递。

代码语言:javascript
复制
class StarburstAPI(object):

    def __init__(self, username=None, password=None, oauth=None, session=None):

        self.api_version = 'v1'
        self.base_url = 'https://starburst.com/api/' + self.api_version

        self.headers = default_headers()
        self.params = {}

        if session is None:
            session = requests.Session()
        self._session = session

        if username is not None or password is not None:
            self._session.auth = (username, password)

        self._session.cookies = self._session.head(self.base_url).cookies
        self._session.headers.update({'Content-Type': 'application/json'})

    
    # Get list of domains
    def list_domains(self):

        url = self.base_url + '/dataProduct/domains/'

        return self._session.get(url)
    

    # Get domain by id
    def get_domain(self, id: str):

        url = self.base_url + '/dataProduct/domains/' + id

        return self._session.get(url)


    # Create domain
    def create_domain(self, data=None, **kw):

        url = self.base_url + '/dataProduct/domains/'

        if data:

            kw = add_json_headers(kw)
            data = json.dumps(data)
            
        return self._session.post(url, data, **kw)


    # Delete domain by id
    def delete_domain(self, id: str):

        url = self.base_url + '/dataProduct/domains/' + id

        return self._session.delete(url)
    

    # Update domain by id
    def update_domain(self, id: str, data=None, **kw):

        url = self.base_url + '/dataProduct/domains/' + id

        if data:

            kw = add_json_headers(kw)
            data = json.dumps(data)

        return self._session.put(url, data, **kw)
EN

回答 1

Code Review用户

发布于 2023-05-02 20:50:16

代码语言:javascript
复制
        self.api_version = 'v1'

不需要创建大量的对象属性,而局部变量就可以了。(变量名很有用,谢谢。)

代码语言:javascript
复制
       api_version = 'v1'

这是另一个nit。

代码语言:javascript
复制
        if session is None:
            session = requests.Session()
        self._session = session

这已经很清楚了。我们可以用这个常见的成语来更简洁地表达它:

代码语言:javascript
复制
        self._session = session or requests.Session()

类似地,您可以编写这个稍微紧凑的表达式:

代码语言:javascript
复制
        if username or password:
            self._session.auth = (username, password)

这并不是完全相同的,但是username of ""空字符串可能没有什么意义。

您可以删除此注释,例如:

代码语言:javascript
复制
    # Get list of domains
    def list_domains(self):

避免不告诉我们代码已经说过的东西的# comments

我们将“如何”,技术细节,放入代码中。我们将“为什么”放在注释或方法docstring中。

http动词

我真的很喜欢{list,create}_domain是不同的方法。保留那个组织。

重复URL和URL父母

您有几个方法将url赋值为这个,再加上它。这似乎让你心烦。我不会太担心的。正如编写的那样,代码非常清晰,维护人员可以很容易地搜索匹配的URL。

您可能会删除url临时变量,而不是只将一个catenation表达式交给.get.post

考虑定义DOMAINS = '/dataProduct/domains/'的显式常量。或者为这个流行的前缀定义一个琐碎的助手。

这个客户端库有时会使'/dataProduct/domains/' + id更加脆弱。在服务器端,烧瓶库会将其拼写为:'/dataProduct/domains/{id}'。考虑采用这样的约定,并解析出每个URL的“变量”部分。请记住,检查对您是可用的。如果除了URL之外,一组方法确实是相同的,那么应该可以将它们定义为一行程序,给出适当的支持例程。

公共父级(例如域)的助手可以帮助简洁地定义紧靠在它下面的几个URL的访问器。

您的.post / .put方法有共同的kw + data需求,可以将其提取为公共助手。

总体上?当然,这段代码是重复的。但也没那么糟。

我想起了单元测试代码,在那里复制-n粘贴(干燥的敌人!)被明确接受为一种良好的做法。为什么?生成易于理解和维护的简单代码。

不要在那些似乎困扰你的“冗长”URL字符串上卖弄自己。跟踪bug的维护者首先需要做的事情之一是,grep用于一个URL或其中的一个片段。OP以非常简单的形式表示URL,这使得代码库很容易实现grep‘。

此代码实现了它的许多设计目标。

我愿意委托或接受它的维护任务。

编辑

假设您有一个函数来计算一些有用的东西,例如方程的根。它还想根据谁的要求来调整自己的行动。学习调用者的名字并不难。

代码语言:javascript
复制
import inspect

def sqrt_and_who_called_me(n):
    """Returns a root, and the name of the calling function."""
    frame = inspect.currentframe()
    return math.sqrt(n), frame.f_back.f_code.co_name


def fn():
    root, name = sqrt_and_who_called_me(2.0)
    assert name == "fn"

而不是fn我们可能有

  • def domains():
  • def domains_id():
  • def domains_a():
  • def domains_b():

一个助手想知道我们在域层次结构中,或者想知道是否有后缀,并且它是{id,a,b}中的一个。

调用方可以在传递给助手的参数中泄露这些命名细节,但这可能不是很枯燥。(例如,名称患有整个Bond = namedtuple('Bond', ...)詹姆斯邦德综合征。)为几个GET / POST例程选择结构化名称可以让助手为每个例程量身定制其行为,同时尽量减少重复。当然,@decorators是工具箱中的另一个工具。

检查frame.f_back.f_back允许您将堆栈向上导航到调用者的调用方,依此类推。

票数 0
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/284771

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档