Fix bad domain: zlovezl.cn->piglei.com

This commit is contained in:
piglei 2023-11-01 21:20:48 +08:00
parent 3bdeda09d9
commit cbe9b3f53c
No known key found for this signature in database
GPG Key ID: 40674C21602973B7
14 changed files with 135 additions and 171 deletions

View File

@ -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)

View File

@ -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/)

View File

@ -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 更多的内存。

View File

@ -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/)

View File

@ -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/)

View File

@ -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/)

View File

@ -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/)

View File

@ -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 编程进阶知识。

View File

@ -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)

View File

@ -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/)

View File

@ -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/)

View File

@ -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/)

View File

@ -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/)

View File

@ -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/)