3 个可以使你的 Python 代码更优雅、可读、直观和易于维护的工具。
-- Nina Zakharenko
致谢
编译自 |
https://opensource.com/article/18/4/elegant-solutions-everyday-python-problems
作者 | Nina Zakharenko
译者 | MjSeven 共计翻译:60篇 贡献时间:172 天
3 个可以使你的 Python 代码更优雅、可读、直观和易于维护的工具。
Python 提供了一组独特的工具和语言特性来使你的代码更加优雅、可读和直观。为正确的问题选择合适的工具,你的代码将更易于维护。在本文中,我们将研究其中的三个工具:魔术方法、迭代器和生成器,以及方法魔术。
魔术方法
魔术方法可以看作是 Python 的管道。它们被称为“底层”方法,用于某些内置的方法、符号和操作。你可能熟悉的常见魔术方法是 ,当我们想要初始化一个类的新实例时,它会被调用。
你可能已经看过其他常见的魔术方法,如 和 。Python 中有一整套魔术方法,通过实现其中的一些方法,我们可以修改一个对象的行为,甚至使其行为类似于内置数据类型,例如数字、列表或字典。
让我们创建一个 类来示例:
该类定义为给定的货币符号和汇率定义了一个货币汇率,指定了一个初始化器(也称为构造函数),并实现 ,因此当我们打印这个类时,我们会看到一个友好的表示,例如 ,这是一个带有货币符号和金额的 实例。最重要的是,它定义了一种方法,允许你使用不同的汇率在不同的货币之间进行转换。
打开 Python shell,假设我们已经定义了使用两种不同货币的食品的成本,如下所示:
我们可以使用魔术方法使得这个类的实例之间可以相互交互。假设我们希望能够将这个类的两个实例一起加在一起,即使它们是不同的货币。为了实现这一点,我们可以在 类上实现 这个魔术方法:
现在我们可以以非常直观的方式使用这个类:
当我们将两个实例加在一起时,我们得到以第一个定义的货币符号所表示的结果。所有的转换都是在底层无缝完成的。如果我们想的话,我们也可以为减法实现 ,为乘法实现 等等。阅读模拟数字类型
[1]
或魔术方法指南
[2]
来获得更多信息。
我们学习到 映射到内置运算符 。其他魔术方法可以映射到像 这样的符号。例如,在字典中通过索引或键来获得一项,其实是使用了 方法:
一些魔术方法甚至映射到内置函数,例如 映射到 。
自定义迭代器
对于新的和经验丰富的 Python 开发者来说,自定义迭代器是一个非常强大的但令人迷惑的主题。
许多内置类型,例如列表、集合和字典,已经实现了允许它们在底层迭代的协议。这使我们可以轻松地遍历它们。
我们如何迭代我们自己的自定义类?首先,让我们来澄清一些术语。
◈ 要成为一个可迭代对象,一个类需要实现
◈ 方法需要返回一个迭代器
◈ 要成为一个迭代器,一个类需要实现 (或在 Python 2
[3]
中是 ),当没有更多的项要迭代时,必须抛出一个 异常。
呼!这听起来很复杂,但是一旦你记住了这些基本概念,你就可以在任何时候进行迭代。
我们什么时候想使用自定义迭代器?让我们想象一个场景,我们有一个 实例在不同的端口上运行不同的服务,如 和 。其中一些服务处于 状态,而其他服务则处于 状态。
当我们遍历 实例时,我们只想遍历那些处于 的服务。让我们创建一个 类:
首先,我们将当前位置初始化为 。然后,我们定义一个 方法来返回下一项。我们还将确保在没有更多项返回时抛出 。到目前为止都很好!现在,让我们实现这个 方法。
我们对列表中的服务进行遍历,而当前的位置小于服务的个数,但只有在服务处于活动状态时才返回。一旦我们遍历完服务,就会抛出一个 异常。
因为我们实现了 方法,当它耗尽时,它会抛出 。我们可以从 返回 ,因为 类遵循 协议。
现在我们可以遍历一个 实例,这将允许我们查看每个处于活动的服务,如下所示:
太棒了,但我们可以做得更好!在这样类似的实例中,我们的迭代器不需要维护大量的状态,我们可以简化代码并使用generator(生成器)
[4]
来代替。
关键字到底是什么?在定义生成器函数时使用 yield。这有点像 ,虽然 在返回值后退出函数,但 会暂停执行直到下次调用它。这允许你的生成器的功能在它恢复之前保持状态。查看yield 的文档
[5]
以了解更多信息。使用生成器,我们不必通过记住我们的位置来手动维护状态。生成器只知道两件事:它现在需要做什么以及计算下一个项目需要做什么。一旦我们到达执行点,即 不再被调用,我们就知道停止迭代。
这是因为一些内置的 Python 魔法。在Python 关于 的文档
[6]
中我们可以看到,如果 是作为一个生成器实现的,它将自动返回一个迭代器对象,该对象提供 和 方法。阅读这篇很棒的文章,深入了解迭代器,可迭代对象和生成器
[7]
。
方法魔法
由于其独特的方面,Python 提供了一些有趣的方法魔法作为语言的一部分。
其中一个例子是别名功能。因为函数只是对象,所以我们可以将它们赋值给多个变量。例如:
我们稍后会看到它的作用。
Python 提供了一个方便的内置函数称为
[8]
,它接受 参数并在 上返回属性 。这种编程方式允许我们访问实例变量和方法。例如:
这是一个很酷的技巧,但是我们如何在实际中使用 呢?让我们看一个例子,我们编写一个小型命令行工具来动态处理命令。
脚本的输出是:
接下来,我们来看看 。例如, 允许你返回一个新的partial 对象
[9]
,它的行为类似 ,参数是 和 。如果传入更多的 ,它们会被附加到 。如果传入更多的 ,它们会扩展并覆盖 。让我们通过一个简短的例子来看看:
让我们看看在我喜欢的一个名为
[10]
的库中的一些示例代码中,这个方法魔术是如何结合在一起的,这是一个(名字起得很 low 的) REST API 客户端,它具有透明的语法,允许你以最小的配置快速构建任何 REST API 原型(不仅仅是 GitHub)。我发现这个项目很有趣,因为它非常强大,但只有大约 400 行 Python 代码。你可以在大约 30 行配置代码中添加对任何 REST API 的支持。 知道协议所需的一切(、、),但它不考虑上游 API。让我们深入到它的实现中。
以下是我们如何为 GitHub API 和任何其他相关连接属性定义端点 URL 的简化版本。在这里查看完整代码
[11]
。
然后,一旦配置了访问令牌
[12]
,就可以开始使用GitHub API
[13]
。
请注意,你要确保 URL 拼写正确,因为我们没有验证 URL。如果 URL 不存在或出现了其他任何错误,将返回 API 抛出的错误。那么,这一切是如何运作的呢?让我们找出答案。首先,我们将查看一个类
[14]
的简化示例:
在 类上的每次调用都会调用类
[15]
作为指定的 。
如果最后一次调用不是 HTTP 方法(如 、 等),则返回带有附加路径的 。否则,它从类
[16]
获取 HTTP 方法对应的正确函数,并返回 。
如果我们给出一个不存在的路径会发生什么?
因为 别名为 :
这真心是一些方法魔术!
了解更多
Python 提供了大量工具,使你的代码更优雅,更易于阅读和理解。挑战在于找到合适的工具来完成工作,但我希望本文为你的工具箱添加了一些新工具。而且,如果你想更进一步,你可以在我的博客nnja.io
[17]
上阅读有关装饰器、上下文管理器、上下文生成器和命名元组的内容。随着你成为一名更好的 Python 开发人员,我鼓励你到那里阅读一些设计良好的项目的源代码。Requests
[18]
和Flask
[19]
是两个很好的起步的代码库。
via:https://opensource.com/article/18/4/elegant-solutions-everyday-python-problems
作者:Nina Zakharenko
[21]
选题:lujun9972译者:MjSeven校对:wxy
本文由LCTT原创编译,Linux中国荣誉推出
领取专属 10元无门槛券
私享最新 技术干货