设计符合 Python 理念的API

编程派微信号:codingpy

本文作者为 Noam Elfanbaum,是以色列的一名 Python 开发者。

本文译者 linkmyth,校对 EarlGrey@编程派。linkmyth 是同济大学的在读硕士,主攻web开发、机器学习等方向。

本文参考了 Kenneth Reitz 的 Requests 库 的 API 设计。

编写软件包(库)时,设计良好的 API 与软件包的功能同样重要(当然,前提是你想让别人使用),那么好的 API 的标准是什么?

在本文中,笔者将会比较 Requests 库和 Urllib 库(属于 Python 标准库)在一些典型的 HTTP 使用场景下的差异,并依此发表一些笔者的看法,同时讨论一下 Requests 库为何在 Python 用户群中成为实际上的标准库。

接下来的讨论中我们将会用到 Python 3.5Requests 2.10.0

这篇文章改编自上周我在本地的 Python 聚会上的演讲。读者可以在这里找到演讲的幻灯片。

Requests 和 Urllib

用例 1:发送 Get 请求

明确(API 端点)优于隐晦

  • Requests 库发送请求的目的更加简明(因此也更加清晰)

  • Urllib 库是在省略data参数的情况下发送 Get 请求,这种方式要更加隐晦

  • Requests 库的函数名清晰地解释了函数的用途

有用的对象表示法

  • 读者观察后可以发现,Requests 库返回一个包含请求状态码的字符串(这是通过__repr()__方法实现的)

  • Urllib 库只返回默认的(模糊的)对象表示

代码片段

requests/api.py:

  • 所有的 HTTP 动作在发送之前都会有类似的处理流程,因此这里实现一个request()函数作为主要的流程控制函数。

  • 所有的 HTTP 动作都有一个对应的“辅助函数”,然后在辅助函数中调用request()函数,这使得我们的函数调用更加明确。

用例 2:获取请求状态码

不需要 getters 和 setters

  • 通过读取属性的方式(而不是调用方法)获取对象的特性能使代码更加清晰。

  • 如果读者接触过其他面向对象的语言(比如说 Java),你可能会通过设置 getters 和 setters 来修改对象的属性。在 Python 中则不必如此,读者只需使用 @property装饰器就能完成这一目标。

代码片段

http/client.py:

  • Urllib 库(或者说 http)用一个“getter”方法返回类的属性

用例 3:编码、发送和解码 POST 请求

常用功能要易于使用

  • Requests 库提供了预置的方法来实现编码数据以及解析 JSON 响应,然而读者在使用 Urllib 库时需要自己实现这些方法。

  • 在设计 API 时读者需要思考:软件包最主要的用途是什么?可以添加哪些接口能更方便的满足这些用途?

同样地,Requests 库也为发送 JSON 数据提供了一种优雅的方式:

用例 4:发送验证过的请求

下面的代码为 HTTP 请求完成了长期的身份认证,同时发送了一个请求:

但是如果我们只需完成一次 HTTP 请求?是否还需要这么多代码?使用 Requests 库只需要下面的代码就可以完成:

import requests

requests.get('https://api.github.com/user', auth=('user', 'pswd'))

同时包含简单用法和高级用法

  • Requests 库既有发送单个请求的简单用法,也拥有发送多个请求的复杂用法。

  • 不要让用户在完成简单任务时也需要经过漫长的过程。

尽量使用 Python 内建的数据结构,而不是创建新的数据结构

  • Requests 库使用 Python 内建的数据结构,这使得它非常易于使用。用户不需要了解 Requests 库内部的结构。

库代码

requests/models.py

  • Requests 库在内部将 (user, pass) 元组转化为一个身份验证类

用例 5:处理错误

让用户选择处理错误的方式

  • 有些程序员倾向于用异常的方式处理错误,而有些则倾向于用检查的方式处理错误。

  • 某些场景下检查的方式更为优雅,而另一些场景下则恰恰相反。

  • 合理的做法是让用户可以选择处理错误的方式。

  • 默认返回错误代码可以实现上面所述的合理做法,而默认采用异常处理错误则无法实现。

用例:

以上所述就是这篇文章的全部内容。在准备这次演讲和这篇文章的过程中,笔者收获颇丰,也希望读者在阅读的过程中同样能有所收获。读者可以通过在文章下方评论或者在 Twitter 上留言的方式(@noamelf)向我提供建议,我非常乐于倾听这些建议。

更新(2016年8月8日)

如果读者在阅读完文章后,像包括笔者在内的很多人一样,对 Requests 库和 Urllib 库的可用性之间存在如此大的差异感到惊讶,那么 Nick Coghlan 在下面的评论和后来的文章(标题的含义一目了然)它解决了什么问题中分享了自己对这个问题的看法。

Python 翻译组是EarlGrey@编程派发起成立的一个专注于 Python 技术内容翻译的小组,目前已有近 30 名 Python 技术爱好者加入。

翻译组出品的内容(包括教程、文档、书籍、视频)将在编程派微信公众号首发,欢迎各位 Python 爱好者推荐相关线索。

推荐线索,可直接在编程派微信公众号推文下留言即可。

相关文章

【全200集】最完整的Python教程,7天零基础入门Python,动画

课程全程以真实案例驱动教学,制作整理不易【点赞 +关】大家的支持是UP长期更新前进的动力!B站粉丝福利可以赠送一套Python相关资料:1-简明Python2-Python编程从入门到实践3-Pyth...

Python目录规范:呐,这个就叫专业!

和大家分享一下Python目录规范,也就是文件夹、py文件、数据、日志文件等如何命名和存放。合理的目录规范就像一个整洁的房间,能让你快速找到想要的东西,也让团队协作更高效。1. 概述这目录规范分为两级...

一篇文章学会golang语法,golang简明教程快速入门

Go(又称Golang)是Google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的编程语言。 —— Go - wikipedia.org1 Go 安装最新版本下载地址官方下载 https...

Python数据工程师必备:十大内置模块全解析

Python是数据工程师常用的编程语言之一。作为数据工程师,你应该熟悉许多Python库。不过,Python的标准库本身就包含了众多功能强大的模块,覆盖了文件操作、数据序列化、文本处理等各种相关任务。...