From cbe9b3f53c5bdd89a9203a0d88ce07ed5259cfb6 Mon Sep 17 00:00:00 2001 From: piglei Date: Wed, 1 Nov 2023 21:20:48 +0800 Subject: [PATCH] Fix bad domain: zlovezl.cn->piglei.com --- README.md | 14 ++--- zh_CN/10-a-good-player-know-the-rules.md | 18 +++--- ...hree-tips-on-writing-file-related-codes.md | 19 +++--- zh_CN/12-write-solid-python-codes-part-1.md | 19 +++--- zh_CN/13-write-solid-python-codes-part-2.md | 15 +++-- zh_CN/14-write-solid-python-codes-part-3.md | 30 ++++----- zh_CN/15-thinking-in-edge-cases.md | 14 ++--- zh_CN/16-stmt-expr-and-walrus-operator.md | 2 +- zh_CN/4-mastering-container-types.md | 62 +++++++++---------- zh_CN/5-function-returning-tips.md | 51 +++++++-------- .../6-three-rituals-of-exceptions-handling.md | 16 +++-- zh_CN/7-two-tips-on-loop-writing.md | 16 ++--- zh_CN/8-tips-on-decorators.md | 13 ++-- zh_CN/9-a-story-on-cyclic-imports.md | 17 +++-- 14 files changed, 135 insertions(+), 171 deletions(-) diff --git a/README.md b/README.md index 401f6fa..1628b62 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ 《Python 工匠》图书首页上线啦!共有 3 章在线内容,欢迎阅读。 -- [图书首页](https://www.zlovezl.cn/book/) -- [第 1 章 变量与注释](https://www.zlovezl.cn/book/ch01_variables.html) -- [第 6 章 循环与可迭代对象](https://www.zlovezl.cn/book/ch06_loop.html) -- [第 10 章 面向对象设计原则](https://www.zlovezl.cn/book/ch10_solid_p1.html) +- [图书首页](https://www.piglei.com/book/) +- [第 1 章 变量与注释](https://www.piglei.com/book/ch01_variables.html) +- [第 6 章 循环与可迭代对象](https://www.piglei.com/book/ch06_loop.html) +- [第 10 章 面向对象设计原则](https://www.piglei.com/book/ch10_solid_p1.html) 图书《Python 工匠》现已正式上市。同开源文章相比,图书的知识结构更为流畅,增加了“函数”“面向对象编程”等核心章节,总内容量几乎翻倍,欢迎购买。 @@ -21,18 +21,18 @@ ## 文章列表 -- 1\. 善用变量改善代码质量 [[图书版:变量与注释](https://www.zlovezl.cn/book/ch01_variables.html)] +- 1\. 善用变量改善代码质量 [[图书版:变量与注释](https://www.piglei.com/book/ch01_variables.html)] - [2. 编写条件分支代码的技巧](zh_CN/2-if-else-block-secrets.md) - [3. 使用数字与字符串的技巧](zh_CN/3-tips-on-numbers-and-strings.md) - [4. 容器的门道](zh_CN/4-mastering-container-types.md) - [5. 让函数返回结果的技巧](zh_CN/5-function-returning-tips.md) - [6. 异常处理的三个好习惯](zh_CN/6-three-rituals-of-exceptions-handling.md) -- 7\. 编写地道循环的两个建议 [[图书版:循环与可迭代对象](https://www.zlovezl.cn/book/ch06_loop.html)] +- 7\. 编写地道循环的两个建议 [[图书版:循环与可迭代对象](https://www.piglei.com/book/ch06_loop.html)] - [8. 使用装饰器的技巧](zh_CN/8-tips-on-decorators.md) - [9. 一个关于模块的小故事](zh_CN/9-a-story-on-cyclic-imports.md) - [10. 做一个精通规则的玩家](zh_CN/10-a-good-player-know-the-rules.md) - [11. 高效操作文件的三个建议](zh_CN/11-three-tips-on-writing-file-related-codes.md) -- 12\. 写好面向对象代码的原则(上) [[图书版:面向对象设计原则(上)](https://www.zlovezl.cn/book/ch10_solid_p1.html)] +- 12\. 写好面向对象代码的原则(上) [[图书版:面向对象设计原则(上)](https://www.piglei.com/book/ch10_solid_p1.html)] - [13. 写好面向对象代码的原则(中)](zh_CN/13-write-solid-python-codes-part-2.md) - [14. 写好面向对象代码的原则(下)](zh_CN/14-write-solid-python-codes-part-3.md) - [15. 在边界处思考](zh_CN/15-thinking-in-edge-cases.md) diff --git a/zh_CN/10-a-good-player-know-the-rules.md b/zh_CN/10-a-good-player-know-the-rules.md index 02041e3..ffd3a7e 100644 --- a/zh_CN/10-a-good-player-know-the-rules.md +++ b/zh_CN/10-a-good-player-know-the-rules.md @@ -5,7 +5,7 @@ > 这是 “Python 工匠”系列的第 10 篇文章。[[查看系列所有文章]](https://github.com/piglei/one-python-craftsman)
- +
编程,其实和玩电子游戏有一些相似之处。你在玩不同游戏前,需要先学习每个游戏的不同规则,只有熟悉和灵活运用游戏规则,才更有可能在游戏中获胜。 @@ -120,11 +120,11 @@ def find_potential_customers_v2(): >>> a - b {1, 7} ``` - + 所以,计算“所有去过普吉岛但没去过新西兰的人”,其实就是一次集合的求差值操作。那么要怎么做,才能把我们的问题套入到集合的游戏规则里去呢? - + ### 利用集合的游戏规则 - + 在 Python 中,如果要把某个东西装到集合或字典里,一定要满足一个基本条件:**“这个东西必须是可以被哈希(Hashable)的”** 。什么是 “Hashable”? 举个例子,Python 里面的所有可变对象,比如字典,就 **不是** Hashable 的。当你尝试把字典放入集合中时,会发生这样的错误: @@ -357,13 +357,11 @@ Python 世界有着一套非常复杂的规则,这些规则的涵盖范围包 ## 附录 - 题图来源: Photo by JESHOOTS.COM on Unsplash -- 更多系列文章地址:https://github.com/piglei/one-python-craftsman +- 更多系列文章地址: 系列其他文章: - [所有文章索引 [Github]](https://github.com/piglei/one-python-craftsman) -- [Python 工匠:编写条件分支代码的技巧](https://www.zlovezl.cn/articles/python-else-block-secrets/) -- [Python 工匠:异常处理的三个好习惯](https://www.zlovezl.cn/articles/three-rituals-of-exceptions-handling/) -- [Python 工匠:编写地道循环的两个建议](https://www.zlovezl.cn/articles/two-tips-on-loop-writing/) - - +- [Python 工匠:编写条件分支代码的技巧](https://www.piglei.com/articles/python-else-block-secrets/) +- [Python 工匠:异常处理的三个好习惯](https://www.piglei.com/articles/three-rituals-of-exceptions-handling/) +- [Python 工匠:编写地道循环的两个建议](https://www.piglei.com/articles/two-tips-on-loop-writing/) diff --git a/zh_CN/11-three-tips-on-writing-file-related-codes.md b/zh_CN/11-three-tips-on-writing-file-related-codes.md index b78264c..1566cd3 100644 --- a/zh_CN/11-three-tips-on-writing-file-related-codes.md +++ b/zh_CN/11-three-tips-on-writing-file-related-codes.md @@ -1,11 +1,11 @@ -# Python 工匠:高效操作文件的三个建议 +# Python 工匠:高效操作文件的三个建议 ## 前言 > 这是 “Python 工匠”系列的第 11 篇文章。[[查看系列所有文章]](https://github.com/piglei/one-python-craftsman)
- +
在这个世界上,人们每天都在用 Python 完成着不同的工作。而文件操作,则是大家最常需要解决的任务之一。使用 Python,你可以轻松为他人生成精美的报表,也可以用短短几行代码快速解析、整理上万份数据文件。 @@ -46,7 +46,7 @@ def unify_ext_with_os_path(path): - [`os.path.join(path, filename)`](https://docs.python.org/3/library/os.path.html#os.path.join):组合需要操作的文件名为绝对路径 - [`os.rename(...)`](https://docs.python.org/3/library/os.html#os.rename):重命名某个文件 -上面的函数虽然可以完成需求,但说句实话,即使在写了很多年 Python 代码后,我依然觉得:**这些函数不光很难记,而且最终的成品代码也不怎么讨人喜欢。** +上面的函数虽然可以完成需求,但说句实话,即使在写了很多年 Python 代码后,我依然觉得:**这些函数不光很难记,而且最终的成品代码也不怎么讨人喜欢。** ### 使用 pathlib 模块改写代码 @@ -192,7 +192,7 @@ def count_nine_v2(fname): 假如我们在讨论的不是 Python,而是其他编程语言。那么可以说上面的代码已经很好了。但是如果你认真分析一下 `count_nine_v2` 函数,你会发现在循环体内部,存在着两个独立的逻辑:**数据生成(read 调用与 chunk 判断)** 与 **数据消费**。而这两个独立逻辑被耦合在了一起。 -正如我在[《编写地道循环》](https://www.zlovezl.cn/articles/two-tips-on-loop-writing/)里所提到的,为了提升复用能力,我们可以定义一个新的 `chunked_file_reader` 生成器函数,由它来负责所有与“数据生成”相关的逻辑。这样 `count_nine_v3` 里面的主循环就只需要负责计数即可。 +正如我在[《编写地道循环》](https://www.piglei.com/articles/two-tips-on-loop-writing/)里所提到的,为了提升复用能力,我们可以定义一个新的 `chunked_file_reader` 生成器函数,由它来负责所有与“数据生成”相关的逻辑。这样 `count_nine_v3` 里面的主循环就只需要负责计数即可。 ```python def chunked_file_reader(fp, block_size=1024 * 8): @@ -379,18 +379,15 @@ def parse(self, source, parser=None): ## 附录 - 题图来源: Photo by Devon Divine on Unsplash -- 更多系列文章地址:https://github.com/piglei/one-python-craftsman +- 更多系列文章地址: 系列其他文章: - [所有文章索引 [Github]](https://github.com/piglei/one-python-craftsman) -- [Python 工匠:编写条件分支代码的技巧](https://www.zlovezl.cn/articles/python-else-block-secrets/) -- [Python 工匠:异常处理的三个好习惯](https://www.zlovezl.cn/articles/three-rituals-of-exceptions-handling/) -- [Python 工匠:编写地道循环的两个建议](https://www.zlovezl.cn/articles/two-tips-on-loop-writing/) - +- [Python 工匠:编写条件分支代码的技巧](https://www.piglei.com/articles/python-else-block-secrets/) +- [Python 工匠:异常处理的三个好习惯](https://www.piglei.com/articles/three-rituals-of-exceptions-handling/) +- [Python 工匠:编写地道循环的两个建议](https://www.piglei.com/articles/two-tips-on-loop-writing/) ## 注解 1. 视机器空闲内存的多少,这个过程可能会消耗比 2GB 更多的内存。 - - diff --git a/zh_CN/12-write-solid-python-codes-part-1.md b/zh_CN/12-write-solid-python-codes-part-1.md index 3279819..00bd16a 100644 --- a/zh_CN/12-write-solid-python-codes-part-1.md +++ b/zh_CN/12-write-solid-python-codes-part-1.md @@ -2,11 +2,10 @@ ## 前言 - > 这是 “Python 工匠”系列的第 12 篇文章。[[查看系列所有文章]](https://github.com/piglei/one-python-craftsman)
- +
Python 是一门支持多种编程风格的语言,面对相同的需求,拥有不同背景的程序员可能会写出风格迥异的 Python 代码。比如一位习惯编写 C 语言的程序员,通常会定义一大堆函数来搞定所有事情,这是[“过程式编程”](https://en.wikipedia.org/wiki/Procedural_programming)的思想。而一位有 Java 背景的程序员则更倾向于设计许多个相互关联的类*(class)*,这是 [“面向对象编程(后简称 OOP)”](https://en.wikipedia.org/wiki/Object-oriented_programming)。 @@ -36,7 +35,7 @@ Python 语言虽然拥有类、继承、多态等核心 OOP 特性,但和那 接下来,让我用一个真实的 Python 代码样例来分别向你诠释这 5 条设计原则。 > 写在最前面的注意事项: -> +> > 0. “原则”不是“法律”,它只起到指导作用,并非不可以违反 > 1. “原则”的后两条与接口(Interface)有关,而 Python 没有接口,所以对这部分的诠释是我的个人理解,与原版可能略有出入 > 2. 文章后面的内容含有大量代码,请做好心理准备 ☕️ @@ -49,7 +48,7 @@ Python 语言虽然拥有类、继承、多态等核心 OOP 特性,但和那 我经常会去上面看一些热门文章,但我觉得每次打开浏览器访问有点麻烦。所以,我准备编写一个脚本,自动抓取 HN 首页 Top5 的新闻标题与链接,并用纯文本的方式写入到文件。方便自己用其他工具阅读。
- + 图:Hacker News 首页截图
@@ -577,18 +576,14 @@ def main(): [<<<上一篇【11.高效操作文件的三个建议】](11-three-tips-on-writing-file-related-codes.md) - ## 附录 - 题图来源: Photo by Kelly Sikkema on Unsplash -- 更多系列文章地址:https://github.com/piglei/one-python-craftsman +- 更多系列文章地址: 系列其他文章: - [所有文章索引 [Github]](https://github.com/piglei/one-python-craftsman) -- [Python 工匠:让函数返回结果的技巧](https://www.zlovezl.cn/articles/function-returning-tips/) -- [Python 工匠:编写地道循环的两个建议](https://www.zlovezl.cn/articles/two-tips-on-loop-writing/) -- [Python 工匠:高效操作文件的三个建议](https://www.zlovezl.cn/articles/three-tips-on-writing-file-related-codes/) - - - +- [Python 工匠:让函数返回结果的技巧](https://www.piglei.com/articles/function-returning-tips/) +- [Python 工匠:编写地道循环的两个建议](https://www.piglei.com/articles/two-tips-on-loop-writing/) +- [Python 工匠:高效操作文件的三个建议](https://www.piglei.com/articles/three-tips-on-writing-file-related-codes/) diff --git a/zh_CN/13-write-solid-python-codes-part-2.md b/zh_CN/13-write-solid-python-codes-part-2.md index b1800b2..7ab7f80 100644 --- a/zh_CN/13-write-solid-python-codes-part-2.md +++ b/zh_CN/13-write-solid-python-codes-part-2.md @@ -5,10 +5,10 @@ > 这是 “Python 工匠”系列的第 13 篇文章。[[查看系列所有文章]](https://github.com/piglei/one-python-craftsman)
- +
-在 [上一篇文章](https://www.zlovezl.cn/articles/write-solid-python-codes-part-1/) 里,我用一个虚拟小项目作为例子,讲解了“SOLID”设计原则中的前两位成员:S *(单一职责原则)* 与 O *(开放-关闭原则)*。 +在 [上一篇文章](https://www.piglei.com/articles/write-solid-python-codes-part-1/) 里,我用一个虚拟小项目作为例子,讲解了“SOLID”设计原则中的前两位成员:S *(单一职责原则)* 与 O *(开放-关闭原则)*。 在这篇文章中,我将继续介绍 SOLID 原则的第三位成员:**L(里氏替换原则)**。 @@ -29,6 +29,7 @@ 同前面的 S 与 O 两个原则的命名方式不同,里氏替换原则 *(Liskov Substitution Principle)* 是直接用它的发明者 [Barbara Liskov](https://en.wikipedia.org/wiki/Barbara_Liskov) 命名的,原文看起来像一个复杂的数学公式: > Let q(x) be a property provable about objects of x of type T. Then q(y) should be provable for objects y of type S where S is a subtype of T. +> > - 出处: [Liskov substitution principle - Wikipedia](https://en.wikipedia.org/wiki/Liskov_substitution_principle) 如果把它比较通俗的翻译过来,大概是这样:**当你使用继承时,子类(派生类)对象应该可以在程序中替代父类(基类)对象使用,而不破坏程序原本的功能。** @@ -344,13 +345,11 @@ class Admin(User): ## 附录 - 题图来源: Photo by NeONBRAND on Unsplash -- 更多系列文章地址:https://github.com/piglei/one-python-craftsman +- 更多系列文章地址: 系列其他文章: - [所有文章索引 [Github]](https://github.com/piglei/one-python-craftsman) -- [Python 工匠:写好面向对象代码的原则(上)](https://www.zlovezl.cn/articles/write-solid-python-codes-part-1/) -- [Python 工匠:编写地道循环的两个建议](https://www.zlovezl.cn/articles/two-tips-on-loop-writing/) -- [Python 工匠:高效操作文件的三个建议](https://www.zlovezl.cn/articles/three-tips-on-writing-file-related-codes/) - - +- [Python 工匠:写好面向对象代码的原则(上)](https://www.piglei.com/articles/write-solid-python-codes-part-1/) +- [Python 工匠:编写地道循环的两个建议](https://www.piglei.com/articles/two-tips-on-loop-writing/) +- [Python 工匠:高效操作文件的三个建议](https://www.piglei.com/articles/three-tips-on-writing-file-related-codes/) diff --git a/zh_CN/14-write-solid-python-codes-part-3.md b/zh_CN/14-write-solid-python-codes-part-3.md index d605c7c..bd1b51f 100644 --- a/zh_CN/14-write-solid-python-codes-part-3.md +++ b/zh_CN/14-write-solid-python-codes-part-3.md @@ -4,11 +4,10 @@ > 这是 “Python 工匠”系列的第 14 篇文章。[[查看系列所有文章]](https://github.com/piglei/one-python-craftsman) -
- +
- + 在这篇文章中,我将继续介绍 SOLID 原则剩下的两位成员:**I(接口隔离原则)** 和 **D(依赖倒置原则)**。为了方便,这篇文章将会使用先 D 后 I 的顺序。 ## D:依赖倒置原则 @@ -32,7 +31,7 @@ 我想要按照来源域名来分组统计条目数量,这样就能知道哪个站在 HN 上最受欢迎。
- + 图:Hacker News 条目来源截图
@@ -91,7 +90,7 @@ Site: latimes.com | Count: 1 `SiteSourceGrouper` 是我们的核心类。为了完成任务,它需要使用 `requests` 模块获取首页内容、`lxml` 模块解析标题。所以,现在的依赖关系是“正向”的,高层模块 `SiteSourceGrouper` 依赖低层模块 `requests`、`lxml`。
- + 图:SiteSourceGrouper 依赖 requests、lxml
@@ -256,7 +255,7 @@ def main(): 做完这些修改后,让我们再看看现在的模块依赖关系:
- + 图:SiteSourceGrouper 和 RemoteHNWebPage 都依赖抽象层 HNWebPage
@@ -291,7 +290,7 @@ def test_grouper_from_local(): 这样就可以在没有外网的服务器上测试 `SiteSourceGrouper` 类的核心逻辑了。 > Hint:其实上面的测试函数 `test_grouper_from_local` 远远算不上一个合格的测试用例。 -> +> > 如果真要测试 `SiteSourceGrouper` 的核心逻辑。我们应该准备一个虚构的 Hacker News 页面 *(比如刚好包含 5 个 来源自 github.com 的条目)*,然后判断结果是否包含 `assert result['github.com] == 5` ### 问题:一定要使用抽象类 abc 吗? @@ -394,7 +393,7 @@ def get_generated_at(self) -> datetime.datetime: 但是,在给 `LocalHNWebPage` 添加 `get_generated_at` 方法时,我碰到了一个问题。`LocalHNWebPage` 是一个完全基于本地页面文件作为数据来源的类,仅仅通过 “static_hn.html” 这么一个本地文件,我根本就没法知道它的内容是什么时候生成的。 -这时我只能选择让它的 `get_generated_at` 方法返回一个错误的结果 *(比如文件的修改时间)*,或者直接抛出异常。无论是哪种做法,我都可能违反 [里式替换原则](https://www.zlovezl.cn/articles/write-solid-python-codes-part-2/)。 +这时我只能选择让它的 `get_generated_at` 方法返回一个错误的结果 *(比如文件的修改时间)*,或者直接抛出异常。无论是哪种做法,我都可能违反 [里式替换原则](https://www.piglei.com/articles/write-solid-python-codes-part-2/)。 > Hint:里式替换原则认为子类(派生类)对象应该可以在程序中替代父类(基类)对象使用,而不破坏程序原本的功能。让方法抛出异常显然破坏了这一点。 @@ -429,7 +428,7 @@ class SiteAchiever: 代码写到这,让我们回头看看上个例子里的 *条目来源分组类 `SiteSourceGrouper`* 。
- + 图:成功违反了 I 协议
@@ -474,7 +473,7 @@ class HNWebPage(ContentOnlyHNWebPage): 同时,对于 `LocalHNWebPage` 类来说,它也只需要实现那个只返回的文本的 `ContentOnlyHNWebPage` 就行。
- + 图:实施接口隔离后的结果
@@ -534,17 +533,14 @@ def is_new_visitor(cookies: Dict) -> bool: [<<<上一篇【13.写好面向对象代码的原则(中)】](13-write-solid-python-codes-part-2.md) - ## 附录 - 题图来源: Photo by Carolina Garcia Tavizon on Unsplash -- 更多系列文章地址:https://github.com/piglei/one-python-craftsman +- 更多系列文章地址: 系列其他文章: - [所有文章索引 [Github]](https://github.com/piglei/one-python-craftsman) -- [Python 工匠:写好面向对象代码的原则(上)](https://www.zlovezl.cn/articles/write-solid-python-codes-part-1/) -- [Python 工匠:写好面向对象代码的原则(中)](https://www.zlovezl.cn/articles/write-solid-python-codes-part-2/) -- [Python 工匠:写好面向对象代码的原则(下)](https://www.zlovezl.cn/articles/write-solid-python-codes-part-3/) - - +- [Python 工匠:写好面向对象代码的原则(上)](https://www.piglei.com/articles/write-solid-python-codes-part-1/) +- [Python 工匠:写好面向对象代码的原则(中)](https://www.piglei.com/articles/write-solid-python-codes-part-2/) +- [Python 工匠:写好面向对象代码的原则(下)](https://www.piglei.com/articles/write-solid-python-codes-part-3/) diff --git a/zh_CN/15-thinking-in-edge-cases.md b/zh_CN/15-thinking-in-edge-cases.md index f4ed6f1..b9f7657 100644 --- a/zh_CN/15-thinking-in-edge-cases.md +++ b/zh_CN/15-thinking-in-edge-cases.md @@ -5,10 +5,10 @@ > 这是 “Python 工匠”系列的第 15 篇文章。[[查看系列所有文章]](https://github.com/piglei/one-python-craftsman)
- +
-2016 年,Linux 操作系统的创造者 Linus Torvalds 参加了一场[ TED 访谈节目](https://www.ted.com/talks/linus_torvalds_the_mind_behind_linux/transcript?language=en)。整个节目的前半部分,主要是他在讲如何在家光着膀子写出 Linux 的故事,没有涉及太多编程相关的事情。 +2016 年,Linux 操作系统的创造者 Linus Torvalds 参加了一场[TED 访谈节目](https://www.ted.com/talks/linus_torvalds_the_mind_behind_linux/transcript?language=en)。整个节目的前半部分,主要是他在讲如何在家光着膀子写出 Linux 的故事,没有涉及太多编程相关的事情。 不过在访谈快结束时,突然出现了一个有趣的环节。主持人向 Linus 提问道:“你曾说过更愿意和那些有着好的 **代码品味** 的人共事,那在你眼里,什么才是好的代码品味?” @@ -159,7 +159,7 @@ def counter_by_collections(l): return result ``` -这样的代码既不用“获取许可”,也无需“请求原谅”。 整个函数只有一个主流程,代码更清晰、更自然。 +这样的代码既不用“获取许可”,也无需“请求原谅”。 整个函数只有一个主流程,代码更清晰、更自然。 为什么 `defaultdict` 可以让边界情况消失?因为究其根本,之前的代码就是少了针对 *“键不存在”* 时的默认处理逻辑。所以,当我们用 `defaultdict` 声明了如何处理这个边界情况时,原本需要手动判断的部分就消失了。 @@ -464,12 +464,10 @@ while True: ## 附录 - 题图来源: Photo by Jessica Ruscello on Unsplash -- 更多系列文章地址:https://github.com/piglei/one-python-craftsman +- 更多系列文章地址: 系列其他文章: - [所有文章索引 [Github]](https://github.com/piglei/one-python-craftsman) -- [Python 工匠:写好面向对象代码的原则(上)](https://www.zlovezl.cn/articles/write-solid-python-codes-part-1/) -- [Python 工匠:让函数返回结果的技巧](https://www.zlovezl.cn/articles/function-returning-tips/) - - +- [Python 工匠:写好面向对象代码的原则(上)](https://www.piglei.com/articles/write-solid-python-codes-part-1/) +- [Python 工匠:让函数返回结果的技巧](https://www.piglei.com/articles/function-returning-tips/) diff --git a/zh_CN/16-stmt-expr-and-walrus-operator.md b/zh_CN/16-stmt-expr-and-walrus-operator.md index 87cbe05..692e6a9 100644 --- a/zh_CN/16-stmt-expr-and-walrus-operator.md +++ b/zh_CN/16-stmt-expr-and-walrus-operator.md @@ -304,4 +304,4 @@ if any((ret := n) % 7 == 0 for n in nums): 希望以上的内容对你有所帮助。 -> 这篇文章属于“Python 工匠”系列,如果你喜欢它,也欢迎了解我的书[《Python工匠:案例、技巧与工程实践》\[试读\]](https://www.zlovezl.cn/book/index.html) | [\[书评\]](https://book.douban.com/subject/35723705/),其中有大量同样风格的 Python 编程进阶知识。 +> 这篇文章属于“Python 工匠”系列,如果你喜欢它,也欢迎了解我的书[《Python工匠:案例、技巧与工程实践》\[试读\]](https://www.piglei.com/book/index.html) | [\[书评\]](https://book.douban.com/subject/35723705/),其中有大量同样风格的 Python 编程进阶知识。 diff --git a/zh_CN/4-mastering-container-types.md b/zh_CN/4-mastering-container-types.md index a4c93cf..cb29ec8 100644 --- a/zh_CN/4-mastering-container-types.md +++ b/zh_CN/4-mastering-container-types.md @@ -5,7 +5,7 @@ > 这是 “Python 工匠”系列的第 4 篇文章。[[查看系列所有文章]](https://github.com/piglei/one-python-craftsman)
-
+
图片来源: "The Humble Mason Jar" by Chiot's Run - 非商业性使用 2.0 通用
@@ -20,29 +20,28 @@ Python 语言自身的内部实现细节也与这些容器类型息息相关。 ### 内容目录 - [Python 工匠:容器的门道](#python-工匠容器的门道) - - [序言](#序言) - - [内容目录](#内容目录) - - [当我们谈论容器时,我们在谈些什么?](#当我们谈论容器时我们在谈些什么) - - [底层看容器](#底层看容器) - - [写更快的代码](#写更快的代码) - - [1. 避免频繁扩充列表/创建新列表](#1-避免频繁扩充列表创建新列表) - - [2. 在列表头部操作多的场景使用 deque 模块](#2-在列表头部操作多的场景使用-deque-模块) - - [3. 使用集合/字典来判断成员是否存在](#3-使用集合字典来判断成员是否存在) - - [高层看容器](#高层看容器) - - [写扩展性更好的代码](#写扩展性更好的代码) - - [面向容器接口编程](#面向容器接口编程) - - [常用技巧](#常用技巧) - - [1. 使用元组改善分支代码](#1-使用元组改善分支代码) - - [2. 在更多地方使用动态解包](#2-在更多地方使用动态解包) - - [3. 使用 next() 函数](#3-使用-next-函数) - - [4. 使用有序字典来去重](#4-使用有序字典来去重) - - [常见误区](#常见误区) - - [1. 当心那些已经枯竭的迭代器](#1-当心那些已经枯竭的迭代器) - - [2. 别在循环体内修改被迭代对象](#2-别在循环体内修改被迭代对象) - - [总结](#总结) - - [系列其他文章](#系列其他文章) - - [注解](#注解) - + - [序言](#序言) + - [内容目录](#内容目录) + - [当我们谈论容器时,我们在谈些什么?](#当我们谈论容器时我们在谈些什么) + - [底层看容器](#底层看容器) + - [写更快的代码](#写更快的代码) + - [1. 避免频繁扩充列表/创建新列表](#1-避免频繁扩充列表创建新列表) + - [2. 在列表头部操作多的场景使用 deque 模块](#2-在列表头部操作多的场景使用-deque-模块) + - [3. 使用集合/字典来判断成员是否存在](#3-使用集合字典来判断成员是否存在) + - [高层看容器](#高层看容器) + - [写扩展性更好的代码](#写扩展性更好的代码) + - [面向容器接口编程](#面向容器接口编程) + - [常用技巧](#常用技巧) + - [1. 使用元组改善分支代码](#1-使用元组改善分支代码) + - [2. 在更多地方使用动态解包](#2-在更多地方使用动态解包) + - [3. 使用 next() 函数](#3-使用-next-函数) + - [4. 使用有序字典来去重](#4-使用有序字典来去重) + - [常见误区](#常见误区) + - [1. 当心那些已经枯竭的迭代器](#1-当心那些已经枯竭的迭代器) + - [2. 别在循环体内修改被迭代对象](#2-别在循环体内修改被迭代对象) + - [总结](#总结) + - [系列其他文章](#系列其他文章) + - [注解](#注解) ### 当我们谈论容器时,我们在谈些什么? @@ -53,7 +52,6 @@ Python 语言自身的内部实现细节也与这些容器类型息息相关。 下面,让我们一起站在这两个不同的层面上,重新认识容器。 - ## 底层看容器 Python 是一门高级编程语言,**它所提供的内置容器类型,都是经过高度封装和抽象后的结果**。和“链表”、“红黑树”、“哈希表”这些名字相比,所有 Python 内建类型的名字,都只描述了这个类型的功能特点,其他人完全没法只通过这些名字了解它们的哪怕一丁点内部细节。 @@ -112,7 +110,7 @@ def validate_name(name): ``` > Hint: 强烈建议阅读 [TimeComplexity - Python Wiki](https://wiki.python.org/moin/TimeComplexity),了解更多关于常见容器类型的时间复杂度相关内容。 -> +> > 如果你对字典的实现细节感兴趣,也强烈建议观看 Raymond Hettinger 的演讲 [Modern Dictionaries(YouTube)](https://www.youtube.com/watch?v=p33CVV29OG8&t=1403s) ## 高层看容器 @@ -316,6 +314,7 @@ user = {**{"name": "piglei"}, **{"movies": ["Fight Club"]}} 除此之外,你还可以在普通赋值语句中使用 `*` 运算符来动态地解包可迭代对象。如果你想详细了解相关内容,可以阅读下面推荐的 PEP。 > Hint:推进动态解包场景扩充的两个 PEP: +> > - [PEP 3132 -- Extended Iterable Unpacking | Python.org](https://www.python.org/dev/peps/pep-3132/) > - [PEP 448 -- Additional Unpacking Generalizations | Python.org](https://www.python.org/dev/peps/pep-0448/) @@ -350,7 +349,7 @@ print(next(i for i in numbers if i % 2 == 0)) ``` > Hint: 在 Python 3.6 中,默认的字典类型修改了实现方式,已经变成有序的了。并且在 Python 3.7 中,该功能已经从 **语言的实现细节** 变成了为 **可依赖的正式语言特性**。 -> +> > 但是我觉得让整个 Python 社区习惯这一点还需要一些时间,毕竟目前“字典是无序的”还是被印在无数本 Python 书上。所以,我仍然建议在一切需要有序字典的地方使用 OrderedDict。 ## 常见误区 @@ -374,7 +373,7 @@ for number in numbers: 而且不光是生成器表达式,Python 3 里的 map、filter 内建函数也都有一样的特点。忽视这个特点很容易导致代码中出现一些难以察觉的 Bug。 -Instagram 就在项目从 Python 2 到 Python 3 的迁移过程中碰到了这个问题。它们在 PyCon 2017 上分享了对付这个问题的故事。访问文章 [Instagram 在 PyCon 2017 的演讲摘要](https://www.zlovezl.cn/articles/instagram-pycon-2017/),搜索“迭代器”可以查看详细内容。 +Instagram 就在项目从 Python 2 到 Python 3 的迁移过程中碰到了这个问题。它们在 PyCon 2017 上分享了对付这个问题的故事。访问文章 [Instagram 在 PyCon 2017 的演讲摘要](https://www.piglei.com/articles/instagram-pycon-2017/),搜索“迭代器”可以查看详细内容。 ### 2. 别在循环体内修改被迭代对象 @@ -422,9 +421,9 @@ print(numbers) ## 系列其他文章 - [所有文章索引 [Github]](https://github.com/piglei/one-python-craftsman) -- [Python 工匠:善用变量改善代码质量](https://www.zlovezl.cn/articles/python-using-variables-well/) -- [Python 工匠:编写条件分支代码的技巧](https://www.zlovezl.cn/articles/python-else-block-secrets/) -- [Python 工匠:使用数字与字符串的技巧](https://www.zlovezl.cn/articles/tips-on-numbers-and-strings/) +- [Python 工匠:善用变量改善代码质量](https://www.piglei.com/articles/python-using-variables-well/) +- [Python 工匠:编写条件分支代码的技巧](https://www.piglei.com/articles/python-else-block-secrets/) +- [Python 工匠:使用数字与字符串的技巧](https://www.piglei.com/articles/tips-on-numbers-and-strings/) ## 注解 @@ -432,4 +431,3 @@ print(numbers) 2. Python 里没有类似其他编程语言里的“Interface 接口”类型,只有类似的“抽象类”概念。为了表达方便,后面的内容均统一使用“接口”来替代“抽象类”。 3. 有没有只实现了 Mapping 但又不是 MutableMapping 的类型?试试 [MappingProxyType({})](https://docs.python.org/3/library/types.html#types.MappingProxyType) 4. 有没有只实现了 Set 但又不是 MutableSet 的类型?试试 [frozenset()](https://docs.python.org/3/library/stdtypes.html#frozenset) - diff --git a/zh_CN/5-function-returning-tips.md b/zh_CN/5-function-returning-tips.md index 9e27fd8..c6f597c 100644 --- a/zh_CN/5-function-returning-tips.md +++ b/zh_CN/5-function-returning-tips.md @@ -5,7 +5,7 @@ > 这是 “Python 工匠”系列的第 5 篇文章。[[查看系列所有文章]](https://github.com/piglei/one-python-craftsman)
- +
毫无疑问,函数是 Python 语言里最重要的概念之一。在编程时,我们将真实世界里的大问题分解为小问题,然后通过一个个函数交出答案。函数既是重复代码的克星,也是对抗代码复杂度的最佳武器。 @@ -23,22 +23,22 @@ Python 函数通过调用 `return` 语句来返回结果。使用 `return value` ### 内容目录 - [Python 工匠:让函数返回结果的技巧](#python-工匠让函数返回结果的技巧) - - [序言](#序言) - - [Python 的函数返回方式](#python-的函数返回方式) - - [内容目录](#内容目录) - - [编程建议](#编程建议) - - [1. 单个函数不要返回多种类型](#1-单个函数不要返回多种类型) - - [2. 使用 partial 构造新函数](#2-使用-partial-构造新函数) - - [3. 抛出异常,而不是返回结果与错误](#3-抛出异常而不是返回结果与错误) - - [4. 谨慎使用 None 返回值](#4-谨慎使用-none-返回值) - - [1. 作为操作类函数的默认返回值](#1-作为操作类函数的默认返回值) - - [2. 作为某些“意料之中”的可能没有的值](#2-作为某些意料之中的可能没有的值) - - [3. 作为调用失败时代表“错误结果”的值](#3-作为调用失败时代表错误结果的值) - - [5. 合理使用“空对象模式”](#5-合理使用空对象模式) - - [6. 使用生成器函数代替返回列表](#6-使用生成器函数代替返回列表) - - [7. 限制递归的使用](#7-限制递归的使用) - - [总结](#总结) - - [附录](#附录) + - [序言](#序言) + - [Python 的函数返回方式](#python-的函数返回方式) + - [内容目录](#内容目录) + - [编程建议](#编程建议) + - [1. 单个函数不要返回多种类型](#1-单个函数不要返回多种类型) + - [2. 使用 partial 构造新函数](#2-使用-partial-构造新函数) + - [3. 抛出异常,而不是返回结果与错误](#3-抛出异常而不是返回结果与错误) + - [4. 谨慎使用 None 返回值](#4-谨慎使用-none-返回值) + - [1. 作为操作类函数的默认返回值](#1-作为操作类函数的默认返回值) + - [2. 作为某些“意料之中”的可能没有的值](#2-作为某些意料之中的可能没有的值) + - [3. 作为调用失败时代表“错误结果”的值](#3-作为调用失败时代表错误结果的值) + - [5. 合理使用“空对象模式”](#5-合理使用空对象模式) + - [6. 使用生成器函数代替返回列表](#6-使用生成器函数代替返回列表) + - [7. 限制递归的使用](#7-限制递归的使用) + - [总结](#总结) + - [附录](#附录) ## 编程建议 @@ -161,12 +161,10 @@ def create_for_input(): - 虽然我在这里鼓励使用异常,但“异常”总是会无法避免的让人 **感到惊讶**,所以,最好在函数文档里说明可能抛出的异常类型 - 异常不同于返回值,它在被捕获前会不断往调用栈上层汇报。所以 `create_item` 的一级调用方完全可以省略异常处理,交由上层处理。这个特点给了我们更多的灵活性,但同时也带来了更大的风险。 - > Hint:如何在编程语言里处理错误,是一个至今仍然存在争议的主题。比如像上面不推荐的多返回值方式,正是缺乏异常的 Go 语言中最核心的错误处理机制。另外,即使是异常机制本身,不同编程语言之间也存在着差别。 -> +> > 异常,或是不异常,都是由语言设计者进行多方取舍后的结果,更多时候不存在绝对性的优劣之分。**但是,单就 Python 语言而言,使用异常来表达错误无疑是更符合 Python 哲学,更应该受到推崇的。** - ### 4. 谨慎使用 None 返回值 `None` 值通常被用来表示 **“某个应该存在但是缺失的东西”**,它在 Python 里是独一无二的存在。很多编程语言里都有与 None 类似的设计,比如 JavaScript 里的 `null`、Go 里的 `nil` 等。因为 None 所拥有的独特 *虚无* 气质,它经常被作为函数返回值使用。 @@ -368,7 +366,7 @@ def foo_func(items): yield item ``` -我在 [系列第 4 篇文章“容器的门道”](https://www.zlovezl.cn/articles/mastering-container-types/) 里详细分析过这个模式,更多细节可以访问文章,搜索 “写扩展性更好的代码” 查看。 +我在 [系列第 4 篇文章“容器的门道”](https://www.piglei.com/articles/mastering-container-types/) 里详细分析过这个模式,更多细节可以访问文章,搜索 “写扩展性更好的代码” 查看。 ### 7. 限制递归的使用 @@ -401,14 +399,11 @@ def foo_func(items): ## 附录 - 题图来源: Dominik Scythe on Unsplash -- 更多系列文章地址:https://github.com/piglei/one-python-craftsman +- 更多系列文章地址: 系列其他文章: - [所有文章索引 [Github]](https://github.com/piglei/one-python-craftsman) -- [Python 工匠:善用变量改善代码质量](https://www.zlovezl.cn/articles/python-using-variables-well/) -- [Python 工匠:编写条件分支代码的技巧](https://www.zlovezl.cn/articles/python-else-block-secrets/) -- [Python 工匠:使用数字与字符串的技巧](https://www.zlovezl.cn/articles/tips-on-numbers-and-strings/) - - - +- [Python 工匠:善用变量改善代码质量](https://www.piglei.com/articles/python-using-variables-well/) +- [Python 工匠:编写条件分支代码的技巧](https://www.piglei.com/articles/python-else-block-secrets/) +- [Python 工匠:使用数字与字符串的技巧](https://www.piglei.com/articles/tips-on-numbers-and-strings/) diff --git a/zh_CN/6-three-rituals-of-exceptions-handling.md b/zh_CN/6-three-rituals-of-exceptions-handling.md index fffe99a..ab67108 100644 --- a/zh_CN/6-three-rituals-of-exceptions-handling.md +++ b/zh_CN/6-three-rituals-of-exceptions-handling.md @@ -5,7 +5,7 @@ > 这是 “Python 工匠”系列的第 6 篇文章。[[查看系列所有文章]](https://github.com/piglei/one-python-craftsman)
- +
如果你用 Python 编程,那么你就无法避开异常,因为异常在这门语言里无处不在。打个比方,当你在脚本执行时按 `ctrl+c` 退出,解释器就会产生一个 `KeyboardInterrupt` 异常。而 `KeyError`、`ValueError`、`TypeError` 等更是日常编程里随处可见的老朋友。 @@ -15,7 +15,7 @@ 在这篇文章里,我会分享与异常处理相关的 3 个好习惯。继续阅读前,我希望你已经了解了下面这些知识点: - 异常的基本语法与用法*(建议阅读官方文档 [“Errors and Exceptions”](https://docs.python.org/3.6/tutorial/errors.html))* -- 为什么要使用异常代替错误返回*(建议阅读[《让函数返回结果的技巧》](https://www.zlovezl.cn/articles/function-returning-tips/))* +- 为什么要使用异常代替错误返回*(建议阅读[《让函数返回结果的技巧》](https://www.piglei.com/articles/function-returning-tips/))* - 为什么在写 Python 时鼓励使用异常 *(建议阅读 [“Write Cleaner Python: Use Exceptions”](https://jeffknupp.com/blog/2013/02/06/write-cleaner-python-use-exceptions/))* ## 三个好习惯 @@ -294,7 +294,7 @@ def upload_avatar(request): ``` > Hint:建议阅读 [PEP 343 -- The "with" Statement | Python.org](https://www.python.org/dev/peps/pep-0343/),了解与上下文管理器有关的更多知识。 -> +> > 模块 [contextlib](https://docs.python.org/3/library/contextlib.html) 也提供了非常多与编写上下文管理器相关的工具函数与样例。 ## 总结 @@ -314,13 +314,11 @@ def upload_avatar(request): ## 附录 - 题图来源: Photo by Bernard Hermant on Unsplash -- 更多系列文章地址:https://github.com/piglei/one-python-craftsman +- 更多系列文章地址: 系列其他文章: - [所有文章索引 [Github]](https://github.com/piglei/one-python-craftsman) -- [Python 工匠:善用变量改善代码质量](https://www.zlovezl.cn/articles/python-using-variables-well/) -- [Python 工匠:编写条件分支代码的技巧](https://www.zlovezl.cn/articles/python-else-block-secrets/) -- [Python 工匠:让程序返回结果的技巧](https://www.zlovezl.cn/articles/function-returning-tips/) - - +- [Python 工匠:善用变量改善代码质量](https://www.piglei.com/articles/python-using-variables-well/) +- [Python 工匠:编写条件分支代码的技巧](https://www.piglei.com/articles/python-else-block-secrets/) +- [Python 工匠:让程序返回结果的技巧](https://www.piglei.com/articles/function-returning-tips/) diff --git a/zh_CN/7-two-tips-on-loop-writing.md b/zh_CN/7-two-tips-on-loop-writing.md index c7578c3..8db9317 100644 --- a/zh_CN/7-two-tips-on-loop-writing.md +++ b/zh_CN/7-two-tips-on-loop-writing.md @@ -5,7 +5,7 @@ > 这是 “Python 工匠”系列的第 7 篇文章。[[查看系列所有文章]](https://github.com/piglei/one-python-craftsman)
- +
循环是一种常用的程序控制结构。我们常说,机器相比人类的最大优点之一,就是机器可以不眠不休的重复做某件事情,但人却不行。而**“循环”**,则是实现让机器不断重复工作的关键概念。 @@ -52,7 +52,7 @@ for i, name in enumerate(names): 使用修饰函数处理可迭代对象,可以在各种方面影响循环代码。而要找到合适的例子来演示这个方法,并不用去太远,内置模块 [itertools](https://docs.python.org/3.6/library/itertools.html) 就是一个绝佳的例子。 -简单来说,itertools 是一个包含很多面向可迭代对象的工具函数集。我在之前的系列文章[《容器的门道》](https://www.zlovezl.cn/articles/mastering-container-types/)里提到过它。 +简单来说,itertools 是一个包含很多面向可迭代对象的工具函数集。我在之前的系列文章[《容器的门道》](https://www.piglei.com/articles/mastering-container-types/)里提到过它。 如果要学习 itertools,那么 [Python 官方文档](https://docs.python.org/3.6/library/itertools.html) 是你的首选,里面有非常详细的模块相关资料。但在这篇文章里,侧重点将和官方文档稍有不同。我会通过一些常见的代码场景,来详细解释它是如何改善循环代码的。 @@ -73,7 +73,6 @@ def find_twelve(num_list1, num_list2, num_list3): 对于这种需要嵌套遍历多个对象的多层循环代码,我们可以使用 [product()](https://docs.python.org/3.6/library/itertools.html#itertools.product) 函数来优化它。`product()` 可以接收多个可迭代对象,然后根据它们的笛卡尔积不断生成结果。 - ```python from itertools import product @@ -311,14 +310,11 @@ def notify_nonsleep_users_in_last_30days(): ## 附录 - 题图来源: Photo by Lai man nung on Unsplash -- 更多系列文章地址:https://github.com/piglei/one-python-craftsman +- 更多系列文章地址: 系列其他文章: - [所有文章索引 [Github]](https://github.com/piglei/one-python-craftsman) -- [Python 工匠:容器的门道](https://www.zlovezl.cn/articles/mastering-container-types/) -- [Python 工匠:编写条件分支代码的技巧](https://www.zlovezl.cn/articles/python-else-block-secrets/) -- [Python 工匠:异常处理的三个好习惯](https://www.zlovezl.cn/articles/three-rituals-of-exceptions-handling/) - - - +- [Python 工匠:容器的门道](https://www.piglei.com/articles/mastering-container-types/) +- [Python 工匠:编写条件分支代码的技巧](https://www.piglei.com/articles/python-else-block-secrets/) +- [Python 工匠:异常处理的三个好习惯](https://www.piglei.com/articles/three-rituals-of-exceptions-handling/) diff --git a/zh_CN/8-tips-on-decorators.md b/zh_CN/8-tips-on-decorators.md index 9517c23..2e0e93c 100644 --- a/zh_CN/8-tips-on-decorators.md +++ b/zh_CN/8-tips-on-decorators.md @@ -5,7 +5,7 @@ > 这是 “Python 工匠”系列的第 8 篇文章。[[查看系列所有文章]](https://github.com/piglei/one-python-craftsman)
- +
装饰器 *(Decorator)* 是 Python 里的一种特殊工具,它为我们提供了一种在函数外部修改函数的灵活能力。它有点像一顶画着独一无二 `@` 符号的神奇帽子,只要将它戴在函数头顶上,就能悄无声息的改变函数本身的行为。 @@ -345,17 +345,14 @@ def decorated(*args, **kwargs): [<<<上一篇【7.编写地道循环的两个建议】](7-two-tips-on-loop-writing.md) - ## 附录 - 题图来源: Photo by Clem Onojeghuo on Unsplash -- 更多系列文章地址:https://github.com/piglei/one-python-craftsman +- 更多系列文章地址: 系列其他文章: - [所有文章索引 [Github]](https://github.com/piglei/one-python-craftsman) -- [Python 工匠:编写条件分支代码的技巧](https://www.zlovezl.cn/articles/python-else-block-secrets/) -- [Python 工匠:异常处理的三个好习惯](https://www.zlovezl.cn/articles/three-rituals-of-exceptions-handling/) -- [Python 工匠:编写地道循环的两个建议](https://www.zlovezl.cn/articles/two-tips-on-loop-writing/) - - +- [Python 工匠:编写条件分支代码的技巧](https://www.piglei.com/articles/python-else-block-secrets/) +- [Python 工匠:异常处理的三个好习惯](https://www.piglei.com/articles/three-rituals-of-exceptions-handling/) +- [Python 工匠:编写地道循环的两个建议](https://www.piglei.com/articles/two-tips-on-loop-writing/) diff --git a/zh_CN/9-a-story-on-cyclic-imports.md b/zh_CN/9-a-story-on-cyclic-imports.md index 86e30c0..0ef3664 100644 --- a/zh_CN/9-a-story-on-cyclic-imports.md +++ b/zh_CN/9-a-story-on-cyclic-imports.md @@ -5,7 +5,7 @@ > 这是 “Python 工匠”系列的第 9 篇文章。[[查看系列所有文章]](https://github.com/piglei/one-python-craftsman)
- +
模块(Module)是我们用来组织 Python 代码的基本单位。很多功能强大的复杂站点,都由成百上千个独立模块共同组成。 @@ -125,7 +125,7 @@ ImportError: cannot import name 'User' from 'fancy_site.users' (.../fancy_site/u 如此一来,整个模块依赖关系成为了环状,程序自然也就没法执行下去了。 -![modules_before](https://www.zlovezl.cn/static/uploaded/2019/05/modules_before.png) +![modules_before](https://www.piglei.com/static/uploaded/2019/05/modules_before.png) 不过,没有什么问题能够难倒一个可以正常访问 Google 的程序员。小 R 随便上网一搜,发现这样的问题很好解决。因为 Python 的 import 语句非常灵活,他只需要 **把在 users 模块内导入 send_sms 函数的语句挪到 `add_notification` 方法内,延缓 import 语句的执行就行啦。** @@ -157,7 +157,7 @@ from .msg_utils import send_sms 新的模块依赖关系如下图所示: -![modules_afte](https://www.zlovezl.cn/static/uploaded/2019/05/modules_after.png) +![modules_afte](https://www.piglei.com/static/uploaded/2019/05/modules_after.png) 在新的模块结构中,整个项目被整齐的分为三层,模块间的依赖关系也变得只有**单向流动**。之前在函数内部 `import` 的“延迟导入”技巧,自然也就没有用武之地了。 @@ -185,14 +185,11 @@ from .msg_utils import send_sms ## 附录 - 题图来源: Photo by Ricardo Gomez Angel on Unsplash -- 更多系列文章地址:https://github.com/piglei/one-python-craftsman +- 更多系列文章地址: 系列其他文章: - [所有文章索引 [Github]](https://github.com/piglei/one-python-craftsman) -- [Python 工匠:编写条件分支代码的技巧](https://www.zlovezl.cn/articles/python-else-block-secrets/) -- [Python 工匠:异常处理的三个好习惯](https://www.zlovezl.cn/articles/three-rituals-of-exceptions-handling/) -- [Python 工匠:编写地道循环的两个建议](https://www.zlovezl.cn/articles/two-tips-on-loop-writing/) - - - +- [Python 工匠:编写条件分支代码的技巧](https://www.piglei.com/articles/python-else-block-secrets/) +- [Python 工匠:异常处理的三个好习惯](https://www.piglei.com/articles/three-rituals-of-exceptions-handling/) +- [Python 工匠:编写地道循环的两个建议](https://www.piglei.com/articles/two-tips-on-loop-writing/)