Fix bad domain: zlovezl.cn->piglei.com
This commit is contained in:
parent
3bdeda09d9
commit
cbe9b3f53c
14
README.md
14
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\. <del>善用变量改善代码质量</del> [[图书版:变量与注释](https://www.zlovezl.cn/book/ch01_variables.html)]
|
||||
- 1\. <del>善用变量改善代码质量</del> [[图书版:变量与注释](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\. <del>编写地道循环的两个建议</del> [[图书版:循环与可迭代对象](https://www.zlovezl.cn/book/ch06_loop.html)]
|
||||
- 7\. <del>编写地道循环的两个建议</del> [[图书版:循环与可迭代对象](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\. <del>写好面向对象代码的原则(上)</del> [[图书版:面向对象设计原则(上)](https://www.zlovezl.cn/book/ch10_solid_p1.html)]
|
||||
- 12\. <del>写好面向对象代码的原则(上)</del> [[图书版:面向对象设计原则(上)](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)
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
> 这是 “Python 工匠”系列的第 10 篇文章。[[查看系列所有文章]](https://github.com/piglei/one-python-craftsman)
|
||||
|
||||
<div style="text-align: center; color: #999; margin: 14px 0 14px;font-size: 12px;">
|
||||
<img src="https://www.zlovezl.cn/static/uploaded/2019/05/jeshoots-com-632498-unsplash_w1280.jpg" width="100%" />
|
||||
<img src="https://www.piglei.com/static/uploaded/2019/05/jeshoots-com-632498-unsplash_w1280.jpg" width="100%" />
|
||||
</div>
|
||||
|
||||
编程,其实和玩电子游戏有一些相似之处。你在玩不同游戏前,需要先学习每个游戏的不同规则,只有熟悉和灵活运用游戏规则,才更有可能在游戏中获胜。
|
||||
|
@ -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
|
||||
- 更多系列文章地址:<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,11 +1,11 @@
|
|||
# Python 工匠:高效操作文件的三个建议
|
||||
# Python 工匠:高效操作文件的三个建议
|
||||
|
||||
## 前言
|
||||
|
||||
> 这是 “Python 工匠”系列的第 11 篇文章。[[查看系列所有文章]](https://github.com/piglei/one-python-craftsman)
|
||||
|
||||
<div style="text-align: center; color: #999; margin: 14px 0 14px;font-size: 12px;">
|
||||
<img src="https://www.zlovezl.cn/static/uploaded/2019/06/devon-divine-1348025-unsplash_1280.jpg" width="100%" />
|
||||
<img src="https://www.piglei.com/static/uploaded/2019/06/devon-divine-1348025-unsplash_1280.jpg" width="100%" />
|
||||
</div>
|
||||
|
||||
在这个世界上,人们每天都在用 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
|
||||
- 更多系列文章地址:<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. <a id="annot1"></a>视机器空闲内存的多少,这个过程可能会消耗比 2GB 更多的内存。
|
||||
|
||||
|
||||
|
|
|
@ -2,11 +2,10 @@
|
|||
|
||||
## 前言
|
||||
|
||||
|
||||
> 这是 “Python 工匠”系列的第 12 篇文章。[[查看系列所有文章]](https://github.com/piglei/one-python-craftsman)
|
||||
|
||||
<div style="text-align: center; color: #999; margin: 14px 0 14px;font-size: 12px;">
|
||||
<img src="https://www.zlovezl.cn/static/uploaded/2019/06/kelly-sikkema-Z9AU36chmQI-unsplash_w1280.jpg" width="100%" />
|
||||
<img src="https://www.piglei.com/static/uploaded/2019/06/kelly-sikkema-Z9AU36chmQI-unsplash_w1280.jpg" width="100%" />
|
||||
</div>
|
||||
|
||||
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 的新闻标题与链接,并用纯文本的方式写入到文件。方便自己用其他工具阅读。
|
||||
|
||||
<div style="text-align: center; color: #999; margin: 14px 0 14px;font-size: 12px;">
|
||||
<img src="https://www.zlovezl.cn/static/uploaded/2019/06/hackernews_frontpage.png" width="100%" />
|
||||
<img src="https://www.piglei.com/static/uploaded/2019/06/hackernews_frontpage.png" width="100%" />
|
||||
图:Hacker News 首页截图
|
||||
</div>
|
||||
|
||||
|
@ -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
|
||||
- 更多系列文章地址:<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/)
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
> 这是 “Python 工匠”系列的第 13 篇文章。[[查看系列所有文章]](https://github.com/piglei/one-python-craftsman)
|
||||
|
||||
<div style="text-align: center; color: #999; margin: 14px 0 14px;font-size: 12px;">
|
||||
<img src="https://www.zlovezl.cn/static/uploaded/2019/11/neonbrand-CXDw96Oy-Yw-unsplash_w1280.jpg" width="100%" />
|
||||
<img src="https://www.piglei.com/static/uploaded/2019/11/neonbrand-CXDw96Oy-Yw-unsplash_w1280.jpg" width="100%" />
|
||||
</div>
|
||||
|
||||
在 [上一篇文章](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
|
||||
- 更多系列文章地址:<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/)
|
||||
|
|
|
@ -4,11 +4,10 @@
|
|||
|
||||
> 这是 “Python 工匠”系列的第 14 篇文章。[[查看系列所有文章]](https://github.com/piglei/one-python-craftsman)
|
||||
|
||||
|
||||
<div style="text-align: center; color: #999; margin: 14px 0 14px;font-size: 12px;">
|
||||
<img src="https://www.zlovezl.cn/static/uploaded/2020/02/carolina-garcia-tavizon-w1280.jpg" width="100%" />
|
||||
<img src="https://www.piglei.com/static/uploaded/2020/02/carolina-garcia-tavizon-w1280.jpg" width="100%" />
|
||||
</div>
|
||||
|
||||
|
||||
在这篇文章中,我将继续介绍 SOLID 原则剩下的两位成员:**I(接口隔离原则)** 和 **D(依赖倒置原则)**。为了方便,这篇文章将会使用先 D 后 I 的顺序。
|
||||
|
||||
## D:依赖倒置原则
|
||||
|
@ -32,7 +31,7 @@
|
|||
我想要按照来源域名来分组统计条目数量,这样就能知道哪个站在 HN 上最受欢迎。
|
||||
|
||||
<div style="text-align: center; color: #999; margin: 14px 0 14px;font-size: 12px;">
|
||||
<img src="https://www.zlovezl.cn/static/uploaded/2020/02/SOLID_3_hn.jpg" width="100%" />
|
||||
<img src="https://www.piglei.com/static/uploaded/2020/02/SOLID_3_hn.jpg" width="100%" />
|
||||
图:Hacker News 条目来源截图
|
||||
</div>
|
||||
|
||||
|
@ -91,7 +90,7 @@ Site: latimes.com | Count: 1
|
|||
`SiteSourceGrouper` 是我们的核心类。为了完成任务,它需要使用 `requests` 模块获取首页内容、`lxml` 模块解析标题。所以,现在的依赖关系是“正向”的,高层模块 `SiteSourceGrouper` 依赖低层模块 `requests`、`lxml`。
|
||||
|
||||
<div style="text-align: center; color: #999; margin: 14px 0 14px;font-size: 12px;">
|
||||
<img src="https://www.zlovezl.cn/static/uploaded/2020/02/SOLID_D_before.png" width="100%" />
|
||||
<img src="https://www.piglei.com/static/uploaded/2020/02/SOLID_D_before.png" width="100%" />
|
||||
图:SiteSourceGrouper 依赖 requests、lxml
|
||||
</div>
|
||||
|
||||
|
@ -256,7 +255,7 @@ def main():
|
|||
做完这些修改后,让我们再看看现在的模块依赖关系:
|
||||
|
||||
<div style="text-align: center; color: #999; margin: 14px 0 14px;font-size: 12px;">
|
||||
<img src="https://www.zlovezl.cn/static/uploaded/2020/02/SOLID_D_after.png" width="100%" />
|
||||
<img src="https://www.piglei.com/static/uploaded/2020/02/SOLID_D_after.png" width="100%" />
|
||||
图:SiteSourceGrouper 和 RemoteHNWebPage 都依赖抽象层 HNWebPage
|
||||
</div>
|
||||
|
||||
|
@ -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`* 。
|
||||
|
||||
<div style="text-align: center; color: #999; margin: 14px 0 14px;font-size: 12px;">
|
||||
<img src="https://www.zlovezl.cn/static/uploaded/2020/02/SOLID_I_before.png" width="100%" />
|
||||
<img src="https://www.piglei.com/static/uploaded/2020/02/SOLID_I_before.png" width="100%" />
|
||||
图:成功违反了 I 协议
|
||||
</div>
|
||||
|
||||
|
@ -474,7 +473,7 @@ class HNWebPage(ContentOnlyHNWebPage):
|
|||
同时,对于 `LocalHNWebPage` 类来说,它也只需要实现那个只返回的文本的 `ContentOnlyHNWebPage` 就行。
|
||||
|
||||
<div style="text-align: center; color: #999; margin: 14px 0 14px;font-size: 12px;">
|
||||
<img src="https://www.zlovezl.cn/static/uploaded/2020/02/SOLID_I_after.png" width="100%" />
|
||||
<img src="https://www.piglei.com/static/uploaded/2020/02/SOLID_I_after.png" width="100%" />
|
||||
图:实施接口隔离后的结果
|
||||
</div>
|
||||
|
||||
|
@ -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
|
||||
- 更多系列文章地址:<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/)
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
> 这是 “Python 工匠”系列的第 15 篇文章。[[查看系列所有文章]](https://github.com/piglei/one-python-craftsman)
|
||||
|
||||
<div style="text-align: center; color: #999; margin: 14px 0 14px;font-size: 12px;">
|
||||
<img src="https://www.zlovezl.cn/static/uploaded/2020/06/jessica-ruscello-DoSDQvzjeH0-unsplash_w1440.jpg" width="100%" />
|
||||
<img src="https://www.piglei.com/static/uploaded/2020/06/jessica-ruscello-DoSDQvzjeH0-unsplash_w1440.jpg" width="100%" />
|
||||
</div>
|
||||
|
||||
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
|
||||
- 更多系列文章地址:<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/)
|
||||
|
|
|
@ -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 编程进阶知识。
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
> 这是 “Python 工匠”系列的第 4 篇文章。[[查看系列所有文章]](https://github.com/piglei/one-python-craftsman)
|
||||
|
||||
<div style="text-align: center; color: #999; margin: 14px 0 14px;font-size: 12px;">
|
||||
<img src="https://www.zlovezl.cn/static//uploaded/2019/01/6002476959_cca2bf5424_b_thumb.jpg" width="100%" /><div>
|
||||
<img src="https://www.piglei.com/static//uploaded/2019/01/6002476959_cca2bf5424_b_thumb.jpg" width="100%" /><div>
|
||||
图片来源: <a href="https://www.flickr.com/photos/chiotsrun/6002476959/in/photolist-a9qgh4-W4eQ1j-7MrCfo-4ARLWp-dwCzHh-Tascu9-RNRbRf-foLHW5-22dkkHM-9ceFA8-aGGd3a-26X3sqQ-iuTwX9-q52ktA-osn2eb-29oujY-6mXd1c-8E92nc-mPbq55-9GuPU8-26Q1NZG-8UL8PL-pdyFsW-7V8ifD-VZavJ8-2cUdHbU-9WrgjZ-6g7M5K-VMLVrb-cXDd4-bygFJG-C76kP-nMQW54-7MoQqn-qA3fud-c92dBU-tAzTBm-7KqFXc-24VvcW1-djQX9e-5LzjkA-63U4kb-bt1EEY-jLRpKo-dQSWBH-aDbqXc-8KhfnE-2m5ZsF-6ciuiR-qwdbt">"The Humble Mason Jar" by Chiot's Run</a> - 非商业性使用 2.0 通用</div>
|
||||
</div>
|
||||
|
||||
|
@ -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. <a id="annot2"></a>Python 里没有类似其他编程语言里的“Interface 接口”类型,只有类似的“抽象类”概念。为了表达方便,后面的内容均统一使用“接口”来替代“抽象类”。
|
||||
3. <a id="annot3"></a>有没有只实现了 Mapping 但又不是 MutableMapping 的类型?试试 [MappingProxyType({})](https://docs.python.org/3/library/types.html#types.MappingProxyType)
|
||||
4. <a id="annot4"></a>有没有只实现了 Set 但又不是 MutableSet 的类型?试试 [frozenset()](https://docs.python.org/3/library/stdtypes.html#frozenset)
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
> 这是 “Python 工匠”系列的第 5 篇文章。[[查看系列所有文章]](https://github.com/piglei/one-python-craftsman)
|
||||
|
||||
<div style="text-align: center; color: #999; margin: 14px 0 14px;font-size: 12px;">
|
||||
<img src="https://www.zlovezl.cn/static/uploaded/2019/03/dominik-scythe-283337-unsplash-w1280.jpg" width="100%" />
|
||||
<img src="https://www.piglei.com/static/uploaded/2019/03/dominik-scythe-283337-unsplash-w1280.jpg" width="100%" />
|
||||
</div>
|
||||
|
||||
毫无疑问,函数是 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
|
||||
- 更多系列文章地址:<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/)
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
> 这是 “Python 工匠”系列的第 6 篇文章。[[查看系列所有文章]](https://github.com/piglei/one-python-craftsman)
|
||||
|
||||
<div style="text-align: center; color: #999; margin: 14px 0 14px;font-size: 12px;">
|
||||
<img src="https://www.zlovezl.cn/static/uploaded/2019/03/bernard-hermant-665508-unsplash_w1280.jpg" width="100%" />
|
||||
<img src="https://www.piglei.com/static/uploaded/2019/03/bernard-hermant-665508-unsplash_w1280.jpg" width="100%" />
|
||||
</div>
|
||||
|
||||
如果你用 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
|
||||
- 更多系列文章地址:<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/)
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
> 这是 “Python 工匠”系列的第 7 篇文章。[[查看系列所有文章]](https://github.com/piglei/one-python-craftsman)
|
||||
|
||||
<div style="text-align: center; color: #999; margin: 14px 0 14px;font-size: 12px;">
|
||||
<img src="https://www.zlovezl.cn/static/uploaded/2019/04/lai-man-nung-1205465-unsplash_w1280.jpg" width="100%" />
|
||||
<img src="https://www.piglei.com/static/uploaded/2019/04/lai-man-nung-1205465-unsplash_w1280.jpg" width="100%" />
|
||||
</div>
|
||||
|
||||
循环是一种常用的程序控制结构。我们常说,机器相比人类的最大优点之一,就是机器可以不眠不休的重复做某件事情,但人却不行。而**“循环”**,则是实现让机器不断重复工作的关键概念。
|
||||
|
@ -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
|
||||
- 更多系列文章地址:<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/)
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
> 这是 “Python 工匠”系列的第 8 篇文章。[[查看系列所有文章]](https://github.com/piglei/one-python-craftsman)
|
||||
|
||||
<div style="text-align: center; color: #999; margin: 14px 0 14px;font-size: 12px;">
|
||||
<img src="https://www.zlovezl.cn/static/uploaded/2019/05/clem-onojeghuo-142120-unsplash_w1280.jpg" width="100%" />
|
||||
<img src="https://www.piglei.com/static/uploaded/2019/05/clem-onojeghuo-142120-unsplash_w1280.jpg" width="100%" />
|
||||
</div>
|
||||
|
||||
装饰器 *(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
|
||||
- 更多系列文章地址:<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/)
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
> 这是 “Python 工匠”系列的第 9 篇文章。[[查看系列所有文章]](https://github.com/piglei/one-python-craftsman)
|
||||
|
||||
<div style="text-align: center; color: #999; margin: 14px 0 14px;font-size: 12px;">
|
||||
<img src="https://www.zlovezl.cn/static/uploaded/2019/05/ricardo-gomez-angel-669574-unsplash_w1280.jpg" width="100%" />
|
||||
<img src="https://www.piglei.com/static/uploaded/2019/05/ricardo-gomez-angel-669574-unsplash_w1280.jpg" width="100%" />
|
||||
</div>
|
||||
|
||||
模块(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
|
||||
- 更多系列文章地址:<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/)
|
||||
|
|
Loading…
Reference in New Issue