diff --git a/CHANGELOG.md b/CHANGELOG.md
old mode 100644
new mode 100755
index 7998bce..f419df0
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,3 +3,5 @@
* 2022-01-20 开始更新[cd4d7c0](https://github.com/satwikkansal/wtfpython/commit/cd4d7c0e340789bd001e5e9eae0e3c5bb7c7f7f1)
* 2022-02-09 更新至[cd4d7c0](https://github.com/satwikkansal/wtfpython/commit/cd4d7c0e340789bd001e5e9eae0e3c5bb7c7f7f1)
+
+* 2022-11-15 更新至[ea1e228](https://github.com/satwikkansal/wtfpython/commit/ea1e228407f2f7efc297e6b773aabf376f6def8e)
\ No newline at end of file
diff --git a/README.md b/README.md
old mode 100644
new mode 100755
index 08416d9..76405cd
--- a/README.md
+++ b/README.md
@@ -2,7 +2,8 @@
What the f*ck Python! 🐍
一些有趣且鲜为人知的 Python 特性.
-翻译版本: [English](https://github.com/satwikkansal/wtfpython) | [Vietnamese Tiếng Việt](https://github.com/vuduclyunitn/wtfptyhon-vi) | [Spanish Español](https://github.com/JoseDeFreitas/wtfpython-es) | [Korean 한국어](https://github.com/buttercrab/wtfpython-ko) | [Add translation](https://github.com/satwikkansal/wtfpython/issues/new?title=Add%20translation%20for%20[LANGUAGE]&body=Expected%20time%20to%20finish:%20[X]%20weeks.%20I%27ll%20start%20working%20on%20it%20from%20[Y].)
+翻译版本: [English](https://github.com/satwikkansal/wtfpython) | [Vietnamese Tiếng Việt](https://github.com/vuduclyunitn/wtfptyhon-vi) | [Spanish Español](https://web.archive.org/web/20220511161045/https://github.com/JoseDeFreitas/wtfpython-es) | [Korean 한국어](https://github.com/buttercrab/wtfpython-ko) | [Russian Русский](https://github.com/frontdevops/wtfpython) | [Add translation](https://github.com/satwikkansal/wtfpython/issues/new?title=Add%20translation%20for%20[LANGUAGE]&body=Expected%20time%20to%20finish:%20[X]%20weeks.%20I%27ll%20start%20working%20on%20it%20from%20[Y].)
+
其他模式: [Interactive](https://mybinder.org/v2/gh/robertparley/wtfpython-cn/master?labpath=irrelevant%2Fwtf.ipynb)
@@ -60,6 +61,7 @@ PS: 如果你不是第一次读了, 你可以在[这里](https://github.com/satw
- [> The disappearing variable from outer scope/消失的外部变量](#-the-disappearing-variable-from-outer-scope消失的外部变量)
- [> The mysterious key type conversion/神秘的键型转换 *](#-the-mysterious-key-type-conversion神秘的键型转换-)
- [> Let's see if you can guess this?/看看你能否猜到这一点?](#-lets-see-if-you-can-guess-this看看你能否猜到这一点)
+ - [> Exceeds the limit for integer string conversion/整型转字符串越界](#-exceeds-the-limit-for-integer-string-conversion整型转字符串越界)
- [Section: Slippery Slopes/滑坡谬误](#section-slippery-slopes滑坡谬误)
- [> Modifying a dictionary while iterating over it/迭代字典时的修改](#-modifying-a-dictionary-while-iterating-over-it迭代字典时的修改)
- [> Stubborn `del` operator/坚强的 `del` *](#-stubborn-del-operator坚强的-del-)
@@ -375,20 +377,20 @@ False
#### 💡 说明:
-根据 https://docs.python.org/2/reference/expressions.html#not-in
+根据 https://docs.python.org/3/reference/expressions.html#comparisons
> 形式上, 如果 a, b, c, ..., y, z 是表达式, 而 op1, op2, ..., opN 是比较运算符, 那么除了每个表达式最多只出现一次以外 a op1 b op2 c ... y opN z 就等于 a op1 b and b op2 c and ... y opN z.
虽然上面的例子似乎很愚蠢, 但是像 `a == b == c` 或 `0 <= x <= 100` 就很棒了.
* `False is False is False` 相当于 `(False is False) and (False is False)`
-* `True is False == False` 相当于 `True is False and False == False`, 由于语句的第一部分 (`True is False`) 等于 `False`, 因此整个表达式的结果为 `False`.
-* `1 > 0 < 1` 相当于 `1 > 0 and 0 < 1`, 所以最终结果为 `True`.
+* `True is False == False` 相当于 `(True is False) and (False == False)`, 由于语句的第一部分 (`True is False`) 等于 `False`, 因此整个表达式的结果为 `False`.
+* `1 > 0 < 1` 相当于 `(1 > 0) and (0 < 1)`, 所以最终结果为 `True`.
* 表达式 `(1 > 0) < 1` 相当于 `True < 1` 且
```py
>>> int(True)
1
- >>> True + 1 # 与这个例子无关,只是好玩
+ >>> True + 1 # 与这个例子无关,只是娱乐一下
2
```
所以, `1 < 1` 等于 `False`
@@ -1975,6 +1977,40 @@ a, b = a[b] = {}, 5
```
+---
+
+### > Exceeds the limit for integer string conversion/整型转字符串越界
+```py
+>>> # Python 3.10.6
+>>> int("2" * 5432)
+
+>>> # Python 3.10.8
+>>> int("2" * 5432)
+```
+
+**Output:**
+```py
+>>> # Python 3.10.6
+222222222222222222222222222222222222222222222222222222222222222...
+
+>>> # Python 3.10.8
+Traceback (most recent call last):
+ ...
+ValueError: Exceeds the limit (4300) for integer string conversion:
+ value has 5432 digits; use sys.set_int_max_str_digits()
+ to increase the limit.
+```
+
+#### 💡 说明:
+
+* 对`int()`的调用在Python 3.10.6中运行良好,但在Python 3.10.8中引发ValueError。请注意,Python仍然可以处理大整数。只有在整型和字符串之间转换时才会出现此错误。
+* 幸运的是,当您希望操作超过允许的位数限制时,可以增加该限制的上限。为此,可以使用以下方法之一:
+ - 使用 -X int_max_str_digits 的命令行参数(例如, python3 -X int_max_str_digits=640)
+ - 使用来自sys模块的set_int_max_str_digits()函数
+ - 设定 PYTHONINTMAXSTRDIGITS 环境变量
+
+更多更改设置上限的操作细节查看[文档](https://docs.python.org/3/library/stdtypes.html#int-max-str-digits)。
+
---
## Section: Slippery Slopes/滑坡谬误
@@ -3768,8 +3804,8 @@ def dict_size(o):
[![Commit id][commit-image]][commit-url]
-[commit-url]: https://github.com/satwikkansal/wtfpython/commit/cd4d7c0e340789bd001e5e9eae0e3c5bb7c7f7f1
-[commit-image]: https://img.shields.io/badge/Commit-30e05a-yellow.svg
+[commit-url]: https://github.com/satwikkansal/wtfpython/commit/ea1e228407f2f7efc297e6b773aabf376f6def8e
+[commit-image]: https://img.shields.io/badge/Commit-ea1e22-yellow.svg
## 996.icu
diff --git a/irrelevant/wtf.ipynb b/irrelevant/wtf.ipynb
old mode 100644
new mode 100755
index 1634fd4..7724ce2
--- a/irrelevant/wtf.ipynb
+++ b/irrelevant/wtf.ipynb
@@ -1,13741 +1,13878 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "What the f*ck Python! 🐍
\n",
- "一些有趣且鲜为人知的 Python 特性.
\n",
- "\n",
- "翻译版本: [English](https://github.com/satwikkansal/wtfpython) | [Vietnamese Tiếng Việt](https://github.com/vuduclyunitn/wtfptyhon-vi) | [Spanish Español](https://github.com/JoseDeFreitas/wtfpython-es) | [Korean 한국어](https://github.com/buttercrab/wtfpython-ko) | [Add translation](https://github.com/satwikkansal/wtfpython/issues/new?title=Add%20translation%20for%20[LANGUAGE]&body=Expected%20time%20to%20finish:%20[X]%20weeks.%20I%27ll%20start%20working%20on%20it%20from%20[Y].)\n",
- "\n",
- "其他模式: [Interactive](...) \n",
- "\n",
- "Python, 是一个设计优美的解释型高级语言, 它提供了很多能让程序员感到舒适的功能特性. 但有的时候, Python 的一些输出结果对于初学者来说似乎并不是那么一目了然.\n",
- "\n",
- "这个有趣的项目意在收集 Python 中那些难以理解和反人类直觉的例子以及鲜为人知的功能特性, 并尝试讨论这些现象背后真正的原理!\n",
- "\n",
- "虽然下面的有些例子并不一定会让你觉得 WTFs, 但它们依然有可能会告诉你一些你所不知道的 Python 有趣特性. 我觉得这是一种学习编程语言内部原理的好办法, 而且我相信你也会从中获得乐趣!\n",
- "\n",
- "如果您是一位经验比较丰富的 Python 程序员, 你可以尝试挑战看是否能一次就找到例子的正确答案. 你可能对其中的一些例子已经比较熟悉了, 那这也许能唤起你当年踩这些坑时的甜蜜回忆 :sweat_smile:\n",
- "\n",
- "PS: 如果你不是第一次读了, 你可以在[这里](https://github.com/satwikkansal/wtfpython/releases/)获取变动内容.\n",
- "\n",
- "那么, 让我们开始吧...\n",
- "\n",
- "# Table of Contents/目录\n",
- "\n",
- "\n",
- "- [Table of Contents/目录](#table-of-contents目录)\n",
- "- [Structure of the Examples/示例结构](#structure-of-the-examples示例结构)\n",
- "- [Usage/用法](#usage用法)\n",
- "- [👀 Examples/示例](#-examples示例)\n",
- " - [Section: Strain your brain!/大脑运动!](#section-strain-your-brain大脑运动)\n",
- " - [> First things first!/要事优先 *](#-First-things-first!/要事优先-*)\n",
- " - [> Strings can be tricky sometimes/微妙的字符串 *](#-strings-can-be-tricky-sometimes微妙的字符串-)\n",
- " - [> Be careful with chained operations/小心链式操作](#-be-careful-with-chained-operations小心链式操作)\n",
- " - [> How not to use `is` operator/为什么不使用 `is` 操作符](#-How-not-to-use-is-operator/为什么不使用-is-操作符-)\n",
- " - [> Hash brownies/是时候来点蛋糕了!](#-Hash-brownies是时候来点蛋糕了)\n",
- " - [> Deep down, we're all the same./本质上,我们都一样. *](#-deep-down-were-all-the-same本质上我们都一样-)\n",
- " - [> Disorder within order/有序中潜藏着无序 *](#-disorder-within-order/有序中潜藏着无序-*)\n",
- " - [> Keep trying.../不停的try *](#-Keep-trying不停的try-)\n",
- " - [> For what?/为什么?](#-for-what为什么)\n",
- " - [> Evaluation time discrepancy/执行时机差异](#-evaluation-time-discrepancy执行时机差异)\n",
- " - [> `is not ...` is not `is (not ...)` / `is not ...` 不是 `is (not ...)`](#-is-not--is-not-is-not-is-not--不是-is-not-)\n",
- " - [> A tic-tac-toe where X wins in the first attempt!/一蹴即至!](#-a-tic-tac-toe-where-x-wins-in-the-first-attempt一蹴即至)\n",
- " - [> Schrödinger's variable/薛定谔的变量 *](#-Schrödingers-variable薛定谔的变量-)\n",
- " - [> The chicken-egg problem/先有鸡还是先有蛋 *](#-the-chicken-egg-problem/先有鸡还是先有蛋-*)\n",
- " - [> Subclass relationships/子类关系 *](#-subclass-relationships子类关系-)\n",
- " - [> Methods equality and identity/方法的相等性和唯一性 *](#-Methods-equality-and-identity/方法的相等性和唯一性-)\n",
- " - [> All-true-ation/返回True的all函数 *](#-All-true-ation/返回True的all函数-)\n",
- " - [> The surprising comma/意外的逗号](#-the-surprising-comma意外的逗号)\n",
- " - [> Strings and the backslashes/字符串与反斜杠](#-strings-and-the-backslashes字符串与反斜杠)\n",
- " - [> not knot!/别纠结!](#-not-knot别纠结)\n",
- " - [> Half triple-quoted strings/三个引号](#-half-triple-quoted-strings三个引号)\n",
- " - [> What's wrong with booleans?/布尔你咋了?](#-whats-wrong-with-booleans布尔你咋了)\n",
- " - [> Class attributes and instance attributes/类属性和实例属性](#-class-attributes-and-instance-attributes类属性和实例属性)\n",
- " - [> yielding None/生成 None](#-yielding-none生成-none)\n",
- " - [> Yielding from... return!/生成器里的return *](#-Yielding-from-return/生成器里的return-)\n",
- " - [> Nan-reflexivity/Nan的自反性](#-Nan-reflexivityNan的自反性)\n",
- " - [> Mutating the immutable!/强人所难](#-mutating-the-immutable强人所难)\n",
- " - [> The disappearing variable from outer scope/消失的外部变量](#-the-disappearing-variable-from-outer-scope消失的外部变量)\n",
- " - [> The mysterious key type conversion/神秘的键型转换 *](#-the-mysterious-key-type-conversion神秘的键型转换-)\n",
- " - [> Let's see if you can guess this?/看看你能否猜到这一点?](#-lets-see-if-you-can-guess-this看看你能否猜到这一点)\n",
- " - [Section: Slippery Slopes/滑坡谬误](#section-slippery-slopes滑坡谬误)\n",
- " - [> Modifying a dictionary while iterating over it/迭代字典时的修改](#-modifying-a-dictionary-while-iterating-over-it迭代字典时的修改)\n",
- " - [> Stubborn `del` operator/坚强的 `del` *](#-stubborn-del-operator坚强的-del-)\n",
- " - [> The out of scope variable/外部作用域变量](#-the-out-of-scope-variable外部作用域变量)\n",
- " - [> Deleting a list item while iterating/迭代列表时删除元素](#-deleting-a-list-item-while-iterating迭代列表时删除元素)\n",
- " - [> Lossy zip of iterators/丢三落四的zip *](#->-Lossy-zip-of-iterators/丢三落四的zip-)\n",
- " - [> Loop variables leaking out!/循环变量泄漏!](#-loop-variables-leaking-out循环变量泄漏)\n",
- " - [> Beware of default mutable arguments!/当心默认的可变参数!](#-beware-of-default-mutable-arguments当心默认的可变参数)\n",
- " - [> Catching the Exceptions/捕获异常](#-catching-the-exceptions捕获异常)\n",
- " - [> Same operands, different story!/同人不同命!](#-same-operands-different-story同人不同命)\n",
- " - [> Name resolution ignoring class scope/忽略类作用域的名称解析](#-name-resolution-ignoring-class-scope忽略类作用域的名称解析)\n",
- " - [> Rounding like a banker/像银行家一样舍入 *](#-rounding-like-a-banker/像银行家一样舍入-)\n",
- " - [> Needles in a Haystack/大海捞针](#-needles-in-a-haystack大海捞针)\n",
- " - [> Splitsies/分割函数](#-Splitsies分割函数-)\n",
- " - [> Wild imports/通配符导入方式 *](#-Wild-imports通配符导入方式-)\n",
- " - [> All sorted?/都排序了吗? *](#-All-sorted都排序了吗-)\n",
- " - [> Midnight time doesn't exist?/不存在的午夜?](#-midnight-time-doesnt-exist不存在的午夜)\n",
- " - [Section: The Hidden treasures!/隐藏的宝藏!](#section-the-hidden-treasures隐藏的宝藏)\n",
- " - [> Okay Python, Can you make me fly?/Python, 可否带我飞? *](#-okay-python-can-you-make-me-flypython-可否带我飞-)\n",
- " - [> `goto`, but why?/`goto`, 但为什么? *](#-goto-but-whygoto-但为什么-)\n",
- " - [> Brace yourself!/做好思想准备 *](#-brace-yourself做好思想准备-)\n",
- " - [> Let's meet Friendly Language Uncle For Life/让生活更友好 *](#-lets-meet-friendly-language-uncle-for-life让生活更友好-)\n",
- " - [> Even Python understands that love is complicated/连Python也知道爱是难言的 *](#-even-python-understands-that-love-is-complicated连Python也知道爱是难言的-)\n",
- " - [> Yes, it exists!/是的, 它存在!](#-yes-it-exists是的-它存在)\n",
- " - [> Ellipsis/省略 *](#-Ellipsis省略-)\n",
- " - [> Inpinity/无限 *](#-inpinity无限-)\n",
- " - [> Let's mangle/修饰时间! *](#-Lets-mangle修饰时间-)\n",
- " - [Section: Appearances are deceptive!/外表是靠不住的!](#section-appearances-are-deceptive外表是靠不住的)\n",
- " - [> Skipping lines?/跳过一行?](#-skipping-lines跳过一行)\n",
- " - [> Teleportation/空间移动 *](#-teleportation空间移动-)\n",
- " - [> Well, something is fishy.../嗯, 有些可疑...](#-well-something-is-fishy嗯有些可疑)\n",
- " - [Section: Miscellaneous/杂项](#section-miscellaneous杂项)\n",
- " - [> `+=` is faster/更快的 `+=` ](#--is-faster更快的-)\n",
- " - [> Let's make a giant string!/来做个巨大的字符串吧!](#-lets-make-a-giant-string来做个巨大的字符串吧)\n",
- " - [> Slowing down `dict` lookups/让字典的查找慢下来 *](#-Slowing-down-dict-lookups让字典的查找慢下来-)\n",
- " - [> Bloating instance `dict`s/变臃肿的`dict`实例们 *](#-Bloating-instance-dicts/变臃肿的dict实例们-)\n",
- " - [> Minor Ones/小知识点](#-minor-ones小知识点)\n",
- "- [Contributing/贡献](#contributing贡献)\n",
- "- [Acknowledgements/致谢](#acknowledgements致谢)\n",
- "- [🎓 License/许可](#-license许可)\n",
- " - [Help/帮助](#help帮助)\n",
- " - [Surprise your geeky pythonist friends?/想给你的极客朋友一个惊喜?](#surprise-your-geeky-pythonist-friends想给你的极客朋友一个惊喜)\n",
- " - [Need a pdf version?/需要来一份pdf版的?](#need-a-pdf-version需要来一份pdf版的)\n",
- " - [Follow Commit/追踪Commit](#follow-commit追踪Commit)\n",
- " - [996.icu](#996icu)\n",
- "\n",
- "\n",
- "\n",
- "# Structure of the Examples/示例结构\n",
- "\n",
- "所有示例的结构都如下所示:\n",
- "\n",
- "> ### > 一个精选的标题 *\n",
- "> 标题末尾的星号表示该示例在第一版中不存在,是最近添加的.\n",
- ">\n",
- "> ```py\n",
- "> # 准备代码.\n",
- "> # 释放魔法...\n",
- "> ```\n",
- ">\n",
- "> **Output (Python version):**\n",
- "> ```py\n",
- "> >>> 触发语句\n",
- "> 出乎意料的输出结果\n",
- "> ```\n",
- "> (可选): 对意外输出结果的简短描述.\n",
- ">\n",
- ">\n",
- "> #### 💡 说明:\n",
- ">\n",
- "> * 简要说明发生了什么以及为什么会发生.\n",
- "> ```py\n",
- "> 如有必要, 举例说明\n",
- "> ```\n",
- "> **Output:**\n",
- "> ```py\n",
- "> >>> 触发语句 # 一些让魔法变得容易理解的例子\n",
- "> # 一些正常的输入\n",
- "> ```\n",
- "\n",
- "**注意:** 所有的示例都在 Python 3.5.2 版本的交互解释器上测试过, 如果不特别说明应该适用于所有 Python 版本.\n",
- "\n",
- "# Usage/用法\n",
- "\n",
- "我个人建议, 最好依次阅读下面的示例, 并对每个示例:\n",
- "- 仔细阅读设置例子最开始的代码. 如果您是一位经验丰富的 Python 程序员, 那么大多数时候您都能成功预期到后面的结果.\n",
- "- 阅读输出结果,\n",
- " + 确认结果是否如你所料.\n",
- " + 确认你是否知道这背后的原理.\n",
- " - 如果不知道, 深呼吸然后阅读说明 (如果你还是看不明白, 别沉默! 可以在[这](https://github.com/satwikkansal/wtfPython)提个 issue).\n",
- " - 如果知道, 给自己点奖励, 然后去看下一个例子.\n",
- "\n",
- "PS: 你也可以在命令行阅读 WTFpython. 我们有 pypi 包 和 npm 包(支持代码高亮).(译: 这两个都是英文版的)\n",
- "\n",
- "安装 npm 包 [`wtfpython`](https://www.npmjs.com/package/wtfpython)\n",
- "```sh\n",
- "$ npm install -g wtfpython\n",
- "```\n",
- "\n",
- "或者, 安装 pypi 包 [`wtfpython`](https://pypi.python.org/pypi/wtfpython)\n",
- "```sh\n",
- "$ pip install wtfpython -U\n",
- "```\n",
- "\n",
- "现在, 在命令行中运行 `wtfpython`, 你就可以开始浏览了.\n",
- "\n",
- "---\n",
- "\n",
- "# 👀 Examples/示例\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "## 托管笔记本指南\n",
- "\n",
- "这只是通过 jupyter notebook 浏览 wtfpython 的实验性尝试。因为一些示例是只读的:\n",
- "- 它们要么需要托管运行时不支持的 Python 版本。\n",
- "- 要么它们无法在此环境中复现。\n",
- "\n",
- "预期的输出已经存在于代码单元之后的折叠单元中。 Google colab 提供 Python2(2.7)和 Python3(3.6,默认)运行环境。 您可以在这些 Python2 特定示例之间切换。 对于特定于其他次要版本的示例,您可以简单地参考折叠的输出(目前无法在托管笔记本中控制次要版本)。 您可以检查当前的活动版本\n",
- "```py\n",
- ">>> import sys\n",
- ">>> sys.version\n",
- "# Prints out Python version here.\n",
- "```\n",
- "\n",
- "话虽如此,大多数示例都按预期工作。 如果您遇到任何问题,请随时查阅 wtfpython 上的原始内容并在 repo 中创建问题。 祝君顺利!\n",
- "---\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Strings can be tricky sometimes/微妙的字符串 *\n",
- "1\\.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "140420665652016\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "a = \"some_string\"\n",
- "id(a)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "140420665652016\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "id(\"some\" + \"_\" + \"string\") # 注意两个的id值是相同的.\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "2\\.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True\n",
- "\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "a = \"wtf\"\n",
- "b = \"wtf\"\n",
- "a is b\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "False\n",
- "\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "a = \"wtf!\"\n",
- "b = \"wtf!\"\n",
- "a is b\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True # 3.7 版本返回结果为 False.\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "a, b = \"wtf!\", \"wtf!\"\n",
- "a is b \n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "3\\.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "'a' * 20 is 'aaaaaaaaaaaaaaaaaaaa'\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "False # 3.7 版本返回结果为 True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "'a' * 21 is 'aaaaaaaaaaaaaaaaaaaaa'\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "很好理解, 对吧?\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "- 这些行为是由于 Cpython 在编译优化时, 某些情况下会尝试使用已经存在的不可变对象而不是每次都创建一个新对象. (这种行为被称作字符串的驻留[string interning])\n",
- "- 发生驻留之后, 许多变量可能指向内存中的相同字符串对象. (从而节省内存)\n",
- "- 在上面的代码中, 字符串是隐式驻留的. 何时发生隐式驻留则取决于具体的实现. 这里有一些方法可以用来猜测字符串是否会被驻留:\n",
- " - 所有长度为 0 和长度为 1 的字符串都被驻留.\n",
- " - 字符串在编译时被实现 (`'wtf'` 将被驻留, 但是 `''.join(['w', 't', 'f'])` 将不会被驻留)\n",
- " - 字符串中只包含字母,数字或下划线时将会驻留. 所以 `'wtf!'` 由于包含 `!` 而未被驻留. 可以在[这里](https://github.com/python/cpython/blob/3.6/Objects/codeobject.c#L19)找到 CPython 对此规则的实现.\n",
- "\n",
- " \n",
- "\n",
- "- 当在同一行将 `a` 和 `b` 的值设置为 `\"wtf!\"` 的时候, Python 解释器会创建一个新对象, 然后同时引用第二个变量(译: 仅适用于3.7以下, 详细情况请看[这里](https://github.com/leisurelicht/wtfpython-cn/issues/13)). 如果你在不同的行上进行赋值操作, 它就不会“知道”已经有一个 `wtf!` 对象 (因为 `\"wtf!\"` 不是按照上面提到的方式被隐式驻留的). 它是一种编译器优化, 特别适用于交互式环境.\n",
- "- 常量折叠(constant folding) 是 Python 中的一种 [窥孔优化(peephole optimization)](https://en.wikipedia.org/wiki/Peephole_optimization) 技术. 这意味着在编译时表达式 `'a'*20` 会被替换为 `'aaaaaaaaaaaaaaaaaaaa'` 以减少运行时的时钟周期. 只有长度小于 20 的字符串才会发生常量折叠. (为啥? 想象一下由于表达式 `'a'*10**10` 而生成的 `.pyc` 文件的大小). 相关的源码实现在[这里](https://github.com/python/cpython/blob/3.6/Python/peephole.c#L288).\n",
- "- 如果你是使用 3.7 版本中运行上述示例代码, 会发现部分代码的运行结果与注释说明相同. 这是因为在 3.7 版本中, 常量折叠已经从窥孔优化器迁移至新的 AST 优化器, 后者可以以更高的一致性来执行优化. (由 Eugene Toder 和 INADA Naoki 在 [bpo-29469](https://bugs.python.org/issue29469) 和 [bpo-11549](https://bugs.python.org/issue11549) 中贡献.) \n",
- "- (译: 但是在最新的 3.8 版本中, 结果又变回去了. 虽然 3.8 版本和 3.7 版本一样, 都是使用 AST 优化器. 目前不确定官方对 3.8 版本的 AST 做了什么调整.)\n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Be careful with chained operations/小心链式操作\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "False\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "(False == False) in [False] # 可以理解\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "False\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "False == (False in [False]) # 可以理解\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True\n",
- "\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "False == False in [False] # 为毛?\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "False\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "True is False == False\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True\n",
- "\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "False is False is False\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "1 > 0 < 1\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "False\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "(1 > 0) < 1\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "False\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "1 > (0 < 1)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "\n",
- "根据 https://docs.python.org/2/reference/expressions.html#not-in\n",
- "\n",
- "> 形式上, 如果 a, b, c, ..., y, z 是表达式, 而 op1, op2, ..., opN 是比较运算符, 那么除了每个表达式最多只出现一次以外 a op1 b op2 c ... y opN z 就等于 a op1 b and b op2 c and ... y opN z.\n",
- "\n",
- "虽然上面的例子似乎很愚蠢, 但是像 `a == b == c` 或 `0 <= x <= 100` 就很棒了.\n",
- "\n",
- "* `False is False is False` 相当于 `(False is False) and (False is False)`\n",
- "* `True is False == False` 相当于 `True is False and False == False`, 由于语句的第一部分 (`True is False`) 等于 `False`, 因此整个表达式的结果为 `False`.\n",
- "* `1 > 0 < 1` 相当于 `1 > 0 and 0 < 1`, 所以最终结果为 `True`.\n",
- "* 表达式 `(1 > 0) < 1` 相当于 `True < 1` 且\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " 1\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " int(True)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " 2\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " True + 1 # 与这个例子无关,只是好玩\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- " 所以, `1 < 1` 等于 `False`\n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > How not to use `is` operator/为什么不使用 `is` 操作符\n",
- "下面是一个在互联网上非常有名的例子.\n",
- "\n",
- "1\\.\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True\n",
- "\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "a = 256\n",
- "b = 256\n",
- "a is b\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "False\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "a = 257\n",
- "b = 257\n",
- "a is b\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "2\\.\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "False\n",
- "\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "a = []\n",
- "b = []\n",
- "a is b\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "a = tuple()\n",
- "b = tuple()\n",
- "a is b\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "3\\.\n",
- "**Output**\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "a, b = 257, 257\n",
- "a is b\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output (Python 3.7.x specifically)**\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "False\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "a, b = 257, 257\n",
- "a is b\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "\n",
- "**`is` 和 `==` 的区别**\n",
- "\n",
- "* `is` 运算符检查两个运算对象是否引用自同一对象 (即, 它检查两个运算对象是否相同).\n",
- "* `==` 运算符比较两个运算对象的值是否相等.\n",
- "* 因此 `is` 代表引用相同, `==` 代表值相等. 下面的例子可以很好的说明这点,\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " [] == []\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " False\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " [] is [] # 这两个空列表位于不同的内存地址.\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**`256` 是一个已经存在的对象, 而 `257` 不是**\n",
- "\n",
- "当你启动Python 的时候, 数值为 `-5` 到 `256` 的对象就已经被分配好了. 这些数字因为经常被使用, 所以会被提前准备好.\n",
- "\n",
- "Python 通过这种创建小整数池的方式来避免小整数频繁的申请和销毁内存空间.\n",
- "\n",
- "引用自 https://docs.python.org/3/c-api/long.html\n",
- "> 当前的实现为-5到256之间的所有整数保留一个整数对象数组, 当你创建了一个该范围内的整数时, 你只需要返回现有对象的引用. 所以改变1的值是有可能的. 我怀疑这种行为在Python中是未定义行为. :-)\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "10922528\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "id(256)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "10922528\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "a = 256\n",
- "b = 256\n",
- "id(a)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "10922528\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "id(b)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "140084850247312\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "id(257)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "140084850247440\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "x = 257\n",
- "y = 257\n",
- "id(x)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "140084850247344\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "id(y)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "这里解释器并没有智能到能在执行 `y = 257` 时意识到我们已经创建了一个整数 `257`, 所以它在内存中又新建了另一个对象.\n",
- "\n",
- "类似的优化也适用于其他**不可变**对象,例如空元组。由于列表是可变的,这就是为什么 `[] is []` 将返回 `False` 而 `() is ()` 将返回 `True`。 这解释了我们的第二个代码段。而第三个呢:\n",
- "\n",
- "**当 `a` 和 `b` 在同一行中使用相同的值初始化时,会指向同一个对象.**\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "140640774013296\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "a, b = 257, 257\n",
- "id(a)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "140640774013296\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "id(b)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "140640774013392\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "a = 257\n",
- "b = 257\n",
- "id(a)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "140640774013488\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "id(b)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "* 当 a 和 b 在同一行中被设置为 `257` 时, Python 解释器会创建一个新对象, 然后同时引用第二个变量. 如果你在不同的行上进行, 它就不会 \"知道\" 已经存在一个 `257` 对象了.\n",
- "* 这是一种特别为交互式环境做的编译器优化. 当你在实时解释器中输入两行的时候, 他们会单独编译, 因此也会单独进行优化. 如果你在 `.py` 文件中尝试这个例子, 则不会看到相同的行为, 因为文件是一次性编译的。这种优化不仅限于整数,它也适用于其他不可变数据类型,例如字符串(查看示例“微妙的字符串”)和浮点数,\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " a, b = 257.0, 257.0\n",
- " a is b\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "* 为什么这不适用于 Python 3.7? 大概是因为此类编译器优化是特定于实现的(即可能随版本、操作系统等而变化)。我仍在试图弄清楚导致问题的具体实现更改,您可以查看此 [问题](https://github.com/satwikkansal/wtfpython/issues/100) 以获取更新。\n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Hash brownies/是时候来点蛋糕了!\n",
- "* hash brownie指一种含有大麻成分的蛋糕, 所以这里是句双关\n",
- "* 这里保留原作者对于标题的翻译\n",
- "\n",
- "\n",
- "\n",
- "1\\.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "some_dict = {}\n",
- "some_dict[5.5] = \"JavaScript\"\n",
- "some_dict[5.0] = \"Ruby\"\n",
- "some_dict[5] = \"Python\"\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "\"JavaScript\"\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "some_dict[5.5]\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "\"Python\"\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "some_dict[5.0] # \"Python\" 消除了 \"Ruby\" 的存在?\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "\"Python\"\n",
- "\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "some_dict[5] \n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "complex\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "complex_five = 5 + 0j\n",
- "type(complex_five)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "\"Python\"\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "some_dict[complex_five]\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "为什么到处都是Python?\n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明\n",
- "\n",
- "\n",
- "* 这个 StackOverflow的 [回答](https://stackoverflow.com/a/32211042/4354153) 漂亮地解释了这背后的基本原理.\n",
- "\n",
- "* Python 字典中键的唯一性是根据 *等价性*,而不是同一性。 因此,即使 `5`、`5.0` 和 `5 + 0j` 是不同类型的不同对象,由于它们是相等的,它们不能都在同一个 `dict`(或 `set`)中。 只要您插入其中任何一个,尝试查找任何不同但等价的键都将使用原始映射值成功(而不是因“KeyError”而失败):\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " 5 == 5.0 == 5 + 0j\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " 5 is not 5.0 is not 5 + 0j\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " some_dict = {}\n",
- " some_dict[5.0] = \"Ruby\"\n",
- " 5.0 in some_dict\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " (5 in some_dict) and (5 + 0j in some_dict)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "* 这在赋值的时候也会生效。因此,当您执行 `some_dict[5] = \"Python\"` 时,Python 会找到具有等价键值 `5.0 -> \"Ruby\"` 的现有项,覆盖其值,并保留原始键值。\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " {5.0: 'Ruby'}\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " some_dict\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " {5.0: 'Python'}\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " some_dict[5] = \"Python\"\n",
- " some_dict\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "* 那么我们如何将键值更新为`5`(而不是`5.0`)? 我们实际上不能原地更新,但是我们可以先删除键(`del some_dict[5.0]`),然后重新赋值(`some_dict[5]`)得到整数`5` 作为键而不是浮点数 `5.0`,尽管这属于极少数情况。\n",
- "\n",
- "* Python 是如何在包含 `5.0` 的字典中找到 `5` 的? Python 只需要花费常数时间,而无需使用哈希函数遍历每一项。当 Python 在 dict 中查找键 `foo` 时,它首先计算 `hash(foo)`(以常数时间运行)。因为在 Python 中,要求相等的对象具有相同的哈希值(此处为[文档](https://docs.python.org/3/reference/datamodel.html#object.__hash__)),`5` 、`5.0` 和 `5 + 0j` 具有相同的哈希值。\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " 5 == 5.0 == 5 + 0j\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " hash(5) == hash(5.0) == hash(5 + 0j)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- " **注意:** 反之不一定正确:具有相等哈希值的对象本身可能不相等。(这是[哈希冲突](https://en.wikipedia.org/wiki/Collision_(computer_science))造成的,这也会降低哈希运算的性能。)\n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Deep down, we're all the same./本质上,我们都一样. *\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "class WTF:\n",
- " pass\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "False\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "WTF() == WTF() # 两个不同的对象应该不相等\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "False\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "WTF() is WTF() # 也不相同\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "hash(WTF()) == hash(WTF()) # 哈希值也应该不同\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "id(WTF()) == id(WTF())\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "\n",
- "* 当调用 `id` 函数时, Python 创建了一个 `WTF` 类的对象并传给 `id` 函数. 然后 `id` 函数获取其id值 (也就是内存地址), 然后丢弃该对象. 该对象就被销毁了.\n",
- "* 当我们连续两次进行这个操作时, Python会将相同的内存地址分配给第二个对象. 因为 (在CPython中) `id` 函数使用对象的内存地址作为对象的id值, 所以两个对象的id值是相同的.\n",
- "* 综上, 对象的id值仅仅在对象的生命周期内唯一. 在对象被销毁之后, 或被创建之前, 其他对象可以具有相同的id值.\n",
- "* 那为什么 `is` 操作的结果为 `False` 呢? 让我们看看这段代码.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " class WTF(object):\n",
- " def __init__(self): print(\"I\")\n",
- " def __del__(self): print(\"D\")\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- " **Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " I\n",
- " I\n",
- " D\n",
- " D\n",
- " False\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " WTF() is WTF()\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " I\n",
- " D\n",
- " I\n",
- " D\n",
- " True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " id(WTF()) == id(WTF())\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- " 正如你所看到的, 对象销毁的顺序是造成所有不同之处的原因.\n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Disorder within order/有序中潜藏着无序 *\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "from collections import OrderedDict\n",
- "\n",
- "dictionary = dict()\n",
- "dictionary[1] = 'a'; dictionary[2] = 'b';\n",
- "\n",
- "ordered_dict = OrderedDict()\n",
- "ordered_dict[1] = 'a'; ordered_dict[2] = 'b';\n",
- "\n",
- "another_ordered_dict = OrderedDict()\n",
- "another_ordered_dict[2] = 'b'; another_ordered_dict[1] = 'a';\n",
- "\n",
- "class DictWithHash(dict):\n",
- " \"\"\"\n",
- " 实现了 __hash__ 魔法方法的dict类\n",
- " \"\"\"\n",
- " __hash__ = lambda self: 0\n",
- "\n",
- "class OrderedDictWithHash(OrderedDict):\n",
- " \"\"\"\n",
- " 实现了 __hash__ 魔法方法的OrderedDict类\n",
- " \"\"\"\n",
- " __hash__ = lambda self: 0\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "dictionary == ordered_dict # 如果 a == b\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "dictionary == another_ordered_dict # 且 b == c\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "False\n",
- "\n",
- "# 众所周知,set数据结构储存不重复元素,\n",
- "# 让我们生成以上字典的 set 数据类型,看看会发生什么……\n",
- "\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "ordered_dict == another_ordered_dict # 那么为什么 c == a 不成立??\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "Traceback (most recent call last):\n",
- " File \"\", line 1, in \n",
- "TypeError: unhashable type: 'dict'\n",
- "\n",
- "# dict类没有实现 __hash__ ,出错可以理解,接下来使用我们派生的类。\n",
- "\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "len({dictionary, ordered_dict, another_ordered_dict})\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "1\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "dictionary = DictWithHash()\n",
- "dictionary[1] = 'a'; dictionary[2] = 'b';\n",
- "ordered_dict = OrderedDictWithHash()\n",
- "ordered_dict[1] = 'a'; ordered_dict[2] = 'b';\n",
- "another_ordered_dict = OrderedDictWithHash()\n",
- "another_ordered_dict[2] = 'b'; another_ordered_dict[1] = 'a';\n",
- "len({dictionary, ordered_dict, another_ordered_dict})\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "2\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "len({ordered_dict, another_ordered_dict, dictionary}) # 交换顺序\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "到底发生了什么?\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "\n",
- "- 等号的传递性没有在 `dictionary`, `ordered_dict` 和 `another_ordered_dict` 之间生效是 `OrderedDict` 类中 `__eq__` 方法的实现方式造成的。根据[文档](https://docs.python.org/3/library/collections.html#ordereddict-objects)以下部分:\n",
- " \n",
- " > 对于 `OrderedDict` 类之间,相等性的判定是位置敏感的,实现类似于 `list(od1.items())==list(od2.items())`。对于 `OrderedDict` 类与其他 `Mapping` 对象(例如`dict` 类),相等性的判定是非位置敏感的。\n",
- "- 这是为了任何使用常规 `dict` 类的地方能够直接使用 `OrderedDict` 对象代替。\n",
- "- 好啦,那为什么改变顺序会影响 `set` 对象生成的长度呢? 答案就是上面说的缺乏等号的传递性。因为 `set` 类是唯一元素的无序集合,元素插入的顺序不应该有影响。但在此例中,确有不同。让我们进一步深入。\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " some_set = set()\n",
- " some_set.add(dictionary) # 涉及的变量是前序片段定义的 mapping 对象\n",
- " ordered_dict in some_set\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " 1\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " some_set.add(ordered_dict)\n",
- " len(some_set)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " another_ordered_dict in some_set\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " 1\n",
- "\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " some_set.add(another_ordered_dict)\n",
- " len(some_set)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " False\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " another_set = set()\n",
- " another_set.add(ordered_dict)\n",
- " another_ordered_dict in another_set\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " 2\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " another_set.add(another_ordered_dict)\n",
- " len(another_set)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " dictionary in another_set\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " 2\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " another_set.add(another_ordered_dict)\n",
- " len(another_set)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- " 因此,不一致性是由于 `another_ordered_dict in another_set` 结果为 `False`。 因为 `ordered_dict` 已经在 `another_set` 中,但如前所述, `ordered_dict == another_ordered_dict` 的结果为 `False`,会在后续再加入 `another_ordered_dict` 到 `another_set` 中。\n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Keep trying.../不停的try *\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "def some_func():\n",
- " try:\n",
- " return 'from_try'\n",
- " finally:\n",
- " return 'from_finally'\n",
- "\n",
- "def another_func(): \n",
- " for _ in range(3):\n",
- " try:\n",
- " continue\n",
- " finally:\n",
- " print(\"Finally!\")\n",
- "\n",
- "def one_more_func(): # A gotcha!\n",
- " try:\n",
- " for i in range(3):\n",
- " try:\n",
- " 1 / i\n",
- " except ZeroDivisionError:\n",
- " # Let's throw it here and handle it outside for loop\n",
- " raise ZeroDivisionError(\"A trivial divide by zero error\")\n",
- " finally:\n",
- " print(\"Iteration\", i)\n",
- " break\n",
- " except ZeroDivisionError as e:\n",
- " print(\"Zero division error occurred\", e)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "'from_finally'\n",
- "\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "some_func()\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "Finally!\n",
- "Finally!\n",
- "Finally!\n",
- "\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "another_func()\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "Traceback (most recent call last):\n",
- " File \"\", line 1, in \n",
- "ZeroDivisionError: division by zero\n",
- "\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "1 / 0\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "Iteration 0\n",
- "\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "one_more_func()\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "\n",
- "- 当在 \"try...finally\" 语句的 `try` 中执行 `return`, `break` 或 `continue` 后, `finally` 子句依然会执行.\n",
- "- 函数的返回值由最后执行的 `return` 语句决定. 由于 `finally` 子句一定会执行, 所以 `finally` 子句中的 `return` 将始终是最后执行的语句.\n",
- "- 这里需要注意的是,如果 finally 子句执行 `return` 或 `break` 语句,临时保存的异常将被丢弃。\n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > For what?/为什么?\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "some_string = \"wtf\"\n",
- "some_dict = {}\n",
- "for i, some_dict[i] in enumerate(some_string):\n",
- " pass\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "{0: 'w', 1: 't', 2: 'f'}\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "some_dict # 创建了索引字典.\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "\n",
- "* [Python 语法](https://docs.python.org/3/reference/grammar.html) 中对 `for` 的定义是:\n",
- " ```\n",
- " for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite]\n",
- " ```\n",
- " 其中 `exprlist` 指分配目标. 这意味着对可迭代对象中的**每一项都会执行**类似 `{exprlist} = {next_value}` 的操作.\n",
- "\n",
- " 一个有趣的例子说明了这一点:\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " for i in range(4):\n",
- " print(i)\n",
- " i = 10\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- " **Output:**\n",
- " ```\n",
- " 0\n",
- " 1\n",
- " 2\n",
- " 3\n",
- " ```\n",
- "\n",
- " 你可曾觉得这个循环只会运行一次?\n",
- "\n",
- " **💡 说明:**\n",
- "\n",
- " - 由于循环在Python中工作方式, 赋值语句 `i = 10` 并不会影响迭代循环, 在每次迭代开始之前, 迭代器(这里指 `range(4)`) 生成的下一个元素就被解包并赋值给目标列表的变量(这里指 `i`)了.\n",
- "\n",
- "* 在每一次的迭代中, `enumerate(some_string)` 函数就生成一个新值 `i` (计数器增加) 并从 `some_string` 中获取一个字符. 然后将字典 `some_dict` 键 `i` (刚刚分配的) 的值设为该字符. 本例中循环的展开可以简化为:\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " i, some_dict[i] = (0, 'w')\n",
- " i, some_dict[i] = (1, 't')\n",
- " i, some_dict[i] = (2, 'f')\n",
- " some_dict\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Evaluation time discrepancy/执行时机差异\n",
- "1\\.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "array = [1, 8, 15]\n",
- "# 一个典型的生成器表达式\n",
- "g = (x for x in array if array.count(x) > 0)\n",
- "array = [2, 8, 22]\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[8]\n"
- ]
- }
- ],
- "source": [
- "print(list(g)) #其他的值去哪儿了?\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "2\\.\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "array_1 = [1,2,3,4]\n",
- "g1 = (x for x in array_1)\n",
- "array_1 = [1,2,3,4,5]\n",
- "\n",
- "array_2 = [1,2,3,4]\n",
- "g2 = (x for x in array_2)\n",
- "array_2[:] = [1,2,3,4,5]\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[1,2,3,4]\n",
- "\n"
- ]
- }
- ],
- "source": [
- "print(list(g1))\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[1,2,3,4,5]\n"
- ]
- }
- ],
- "source": [
- "print(list(g2))\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "3\\.\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "array_3 = [1, 2, 3]\n",
- "array_4 = [10, 20, 30]\n",
- "gen = (i + j for i in array_3 for j in array_4)\n",
- "\n",
- "array_3 = [4, 5, 6]\n",
- "array_4 = [400, 500, 600]\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[401, 501, 601, 402, 502, 602, 403, 503, 603]\n"
- ]
- }
- ],
- "source": [
- "print(list(gen))\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明\n",
- "\n",
- "- 在[生成器](https://wiki.python.org/moin/Generators)表达式中, `in` 子句在声明时执行, 而条件子句则是在运行时执行.\n",
- "- 所以在运行前, `array` 已经被重新赋值为 `[2, 8, 22]`, 因此对于之前的 `1`, `8` 和 `15`, 只有 `count(8)` 的结果是大于 `0` 的, 所以生成器只会生成 `8`.\n",
- "- 第二部分中 `g1` 和 `g2` 的输出差异则是由于变量 `array_1` 和 `array_2` 被重新赋值的方式导致的.\n",
- "- 在第一种情况下, `array_1` 被绑定到新对象 `[1,2,3,4,5]`, 因为 `in` 子句是在声明时被执行的, 所以它仍然引用旧对象 `[1,2,3,4]`(并没有被销毁).\n",
- "- 在第二种情况下, 对 `array_2` 的切片赋值将相同的旧对象 `[1,2,3,4]` 原地更新为 `[1,2,3,4,5]`. 因此 `g2` 和 `array_2` 仍然引用同一个对象(这个对象现在已经更新为 `[1,2,3,4,5]`).\n",
- "- 好啦,按照目前讨论的逻辑,第三个代码段中的 `list(gen)` 的值不应该是 `[11, 21, 31, 12, 22, 32, 13, 23, 33]` 吗? (毕竟 `array_3` 和 `array_4` 的行为与 `array_1` 一样)。 [PEP-289](https://www.python.org/dev/peps/pep-0289/#the-details) 中解释了(只有)`array_4` 值更新的原因\n",
- " > 只有最外层的 for 表达式会立即计算,其他表达式会延迟到生成器运行。\n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > `is not ...` is not `is (not ...)`/`is not ...` 不是 `is (not ...)`\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "'something' is not None\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "False\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "'something' is (not None)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "\n",
- "- `is not` 是个单独的二元运算符, 与分别使用 `is` 和 `not` 不同.\n",
- "- 如果操作符两侧的变量指向同一个对象, 则 `is not` 的结果为 `False`, 否则结果为 `True`.\n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > A tic-tac-toe where X wins in the first attempt!/一蹴即至!\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 我们先初始化一个变量row\n",
- "row = [\"\"]*3 #row i['', '', '']\n",
- "# 并创建一个变量board\n",
- "board = [row]*3\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "[['', '', ''], ['', '', ''], ['', '', '']]\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "board\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "['', '', '']\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "board[0]\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "''\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "board[0][0]\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "[['X', '', ''], ['X', '', ''], ['X', '', '']]\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "board[0][0] = \"X\"\n",
- "board\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "我们有没有赋值过3个 \"X\" 呢?\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "\n",
- "当我们初始化 `row` 变量时, 下面这张图展示了内存中的情况。\n",
- "\n",
- "![image](/images/tic-tac-toe/after_row_initialized.png)\n",
- "\n",
- "而当通过对 `row` 做乘法来初始化 `board` 时, 内存中的情况则如下图所示 (每个元素 `board[0]`, `board[1]` 和 `board[2]` 都和 `row` 一样引用了同一列表.)\n",
- "\n",
- "![image](/images/tic-tac-toe/after_board_initialized.png)\n",
- "\n",
- "我们可以通过不使用变量 `row` 生成 `board` 来避免这种情况. ([这个](https://github.com/satwikkansal/wtfpython/issues/68)issue提出了这个需求.)\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "[['X', '', ''], ['', '', ''], ['', '', '']]\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "board = [['']*3 for _ in range(3)]\n",
- "board[0][0] = \"X\"\n",
- "board\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Schrödinger's variable/薛定谔的变量 *\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "funcs = []\n",
- "results = []\n",
- "for x in range(7):\n",
- " def some_func():\n",
- " return x\n",
- " funcs.append(some_func)\n",
- " results.append(some_func()) # 注意这里函数被执行了\n",
- "\n",
- "funcs_results = [func() for func in funcs]\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "[0, 1, 2, 3, 4, 5, 6]\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "results\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "[6, 6, 6, 6, 6, 6, 6]\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "funcs_results\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "即使每次在迭代中将 `some_func` 加入 `funcs` 前的 `x` 值都不相同, 所有的函数还是都返回6.\n",
- "\n",
- "// 再换个例子\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "[512, 512, 512, 512, 512, 512, 512, 512, 512, 512]\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "powers_of_x = [lambda x: x**i for i in range(10)]\n",
- "[f(2) for f in powers_of_x]\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "\n",
- "- 当在循环内部定义一个函数时, 如果该函数在其主体中使用了循环变量, 则闭包函数将与循环变量绑定, 而不是它的值. 因此, 所有的函数都是使用最后分配给变量的值来进行计算的.\n",
- "\n",
- "- 可以通过将循环变量作为命名变量传递给函数来获得预期的结果. **为什么这样可行?** 因为这会在函数内再次定义一个局部变量。我们可以看到它使用了来自上下文的`x`(即*不是*局部变量):\n",
- "(译者注: inspect位于Python标准库中,该模块用于收集python对象的信息,可以获取类或函数的参数的信息,源码,解析堆栈,对对象进行类型检查等等,Python3.3+版本支持getclosurevars函数)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "ClosureVars(nonlocals={}, globals={'x': 6}, builtins={}, unbound=set())\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "import inspect\n",
- "inspect.getclosurevars(funcs[0])\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "由于 `x` 是一个全局值,我们可以通过更新 `x` 来更改 `funcs` 用来查找和返回的值:\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "[42, 42, 42, 42, 42, 42, 42]\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "x = 42\n",
- "[func() for func in funcs]\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "* 要获得想要的结果,您可以将循环变量作为命名变量传递给函数。 **为什么会这样?** 因为这会在函数的作用域内定义变量。 它将不再进入周围(全局)范围来查找变量值,而是会创建一个局部变量来存储该时间点的“x”值。\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "funcs = []\n",
- "for x in range(7):\n",
- " def some_func(x=x):\n",
- " return x\n",
- " funcs.append(some_func)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "[0, 1, 2, 3, 4, 5, 6]\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "funcs_results = [func() for func in funcs]\n",
- "funcs_results\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "此时,不再使用全局变量 `x`:\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "ClosureVars(nonlocals={}, globals={}, builtins={}, unbound=set())\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "inspect.getclosurevars(funcs[0])\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > The chicken-egg problem/先有鸡还是先有蛋 *\n",
- "1\\.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "isinstance(3, int)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "isinstance(type, object)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "isinstance(object, type)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "那么到底谁是“最终”的基类呢?下边顺便列出更多的令人困惑的地方\n",
- "\n",
- "2\\. \n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "False\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "class A: pass\n",
- "isinstance(A, A)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "isinstance(type, type)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "isinstance(object, object)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "3\\.\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "issubclass(int, object)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "issubclass(type, object)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "False\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "issubclass(object, type)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明\n",
- "\n",
- "- `type` 是 Python 中的[元类](https://realpython.com/python-metaclasses/)。\n",
- "- Python 中,**一切**皆对象,其中包括类及其对象(实例)。\n",
- "- `type` 类型是`object`类的元类,每个类(包括`type`)都直接或间接地继承自`object`。\n",
- "- 对象和类型之间没有真正的基类。上述片段中的令人困惑的地方之所以出现,是因为我们从 Python 类的角度考虑这些关系(issubclass 和 isinstance)。 `object`和`type`之间的关系不能在纯python中重现。 更准确地说,以下关系不能在纯 Python 中重现:\n",
- " + A类是B类的一个实例,B类是A类的一个实例。\n",
- " + A类是它自己的一个实例。\n",
- "- `object`和`type`之间的关系(既是彼此的实例,也是它们自己的实例)存在于 Python 中,这是源于实现层级上的“作弊”行为。\n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Subclass relationships/子类关系 *\n",
- "**Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "from collections import Hashable\n",
- "issubclass(list, object)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "issubclass(object, Hashable)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "False\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "issubclass(list, Hashable)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "子类关系应该是可传递的, 对吧? (即, 如果 `A` 是 `B` 的子类, `B` 是 `C` 的子类, 那么 `A` _应该_ 是 `C` 的子类.)\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "\n",
- "* Python 中的子类关系并不一定是传递的. 任何人都可以在元类中随意定义 `__subclasscheck__`.\n",
- "* 当 `issubclass(cls, Hashable)` 被调用时, 它只是在 `cls` 中寻找 `__hash__` 方法或者从继承的父类中寻找 `__hash__` 方法.\n",
- "* 由于 `object` is 可散列的(hashable), 但是 `list` 是不可散列的, 所以它打破了这种传递关系.\n",
- "* 在[这里](https://www.naftaliharris.com/blog/python-subclass-intransitivity/)可以找到更详细的解释.\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Methods equality and identity/方法的相等性和唯一性 *\n",
- "1.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "class SomeClass:\n",
- " def method(self):\n",
- " pass\n",
- "\n",
- " @classmethod\n",
- " def classm(cls):\n",
- " pass\n",
- "\n",
- " @staticmethod\n",
- " def staticm():\n",
- " pass\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "print(SomeClass.method is SomeClass.method)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "False\n"
- ]
- }
- ],
- "source": [
- "print(SomeClass.classm is SomeClass.classm)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "print(SomeClass.classm == SomeClass.classm)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "print(SomeClass.staticm is SomeClass.staticm)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "访问 `classm` 两次,我们得到一个相等的对象,但不是*同一个*? 让我们看看 `SomeClass` 的实例会发生什么:\n",
- "\n",
- "2.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "o1 = SomeClass()\n",
- "o2 = SomeClass()\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "False\n"
- ]
- }
- ],
- "source": [
- "print(o1.method == o2.method)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "print(o1.method == o1.method)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "False\n"
- ]
- }
- ],
- "source": [
- "print(o1.method is o1.method)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "False\n"
- ]
- }
- ],
- "source": [
- "print(o1.classm is o1.classm)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "print(o1.classm == o1.classm == o2.classm == SomeClass.classm)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "print(o1.staticm is o1.staticm is o2.staticm is SomeClass.staticm)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "访问 ` classm` or `method` 两次, 为 `SomeClass` 的同一个实例创建了相等但是*不同*的对象。\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明\n",
- "* 函数是[描述符](https://docs.python.org/3/howto/descriptor.html)。每当将函数作为属性访问时,就会调用描述符,创建一个方法对象,该对象将函数与拥有该属性的对象“绑定”。如果被调用,该方法调用函数,隐式传递绑定对象作为第一个参数(这就是我们如何将 self 作为第一个参数获取,尽管没有显式传递它)。\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- ">\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "o1.method\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "* 多次访问该属性,每次都会创建一个方法对象! 因此,`o1.method is o1.method` 永远不会是真的。但是,将函数作为类属性(而不是实例)访问并不会创建方法对象,所以 `SomeClass.method is SomeClass.method` 是真的。\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "SomeClass.method\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "* `classmethod` 将函数转换为类方法。 类方法是描述符,当被访问时,它会创建一个绑定*类本身*的方法对象,而不是对象本身。\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- ">\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "o1.classm\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "* 与函数不同,`classmethod` 在作为类属性访问时也会创建一个方法(在这种情况下,它们绑定类,而不是类的类型)。 所以 `SomeClass.classm is SomeClass.classm` 是假的。\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- ">\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "SomeClass.classm\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "* 当两个函数相等并且绑定的对象相同时,方法对象比较相等。 所以`o1.method == o1.method` 为真,尽管它们在内存中是两个不同的对象。\n",
- "* `staticmethod` 将函数转换为“无操作”描述符,它按原样返回函数。没有方法对象被创建,所以 `is` 的比较运算为真。\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "o1.staticm\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "SomeClass.staticm\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "* 每次 Python 调用实例方法时都必须创建新的“方法”对象,并且每次都必须修改参数以插入 `self` 严重影响性能。CPython 3.7 [解决了这个问题](https://bugs.python.org/issue26110) 。通过引入新的操作码来处理调用方法而不创建临时方法对象。这仅在实际调用访问的函数时使用,因此这里的代码片段不受影响,仍然会生成方法:)\n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > All-true-ation/返回True的all函数 *\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "all([True, True, True])\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "False\n",
- "\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "all([True, True, False])\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "all([])\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "False\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "all([[]])\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "all([[[]]])\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "为什么会有这种True-False的变化?\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明\n",
- "\n",
- "- `all` 函数的实现等价于:\n",
- "\n",
- "- ```py\n",
- " def all(iterable):\n",
- " for element in iterable:\n",
- " if not element:\n",
- " return False\n",
- " return True\n",
- " ```\n",
- "\n",
- "- `all([])` 返回 `True` 因为可迭代对象为空。 \n",
- "- `all([[]])` 返回 `False` 因为传入的数组有一个元素 `[]`, 在Python中,空列表为假。\n",
- "- `all([[[]]])` 和更高的递归变体总是`True`。 这是因为传递的数组的单个元素(`[[...]]`)不再是空的,而有值的列表为真。\n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > The surprising comma/意外的逗号\n",
- "**Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " File \"\", line 1\n",
- " def h(x, **kwargs,):\n",
- " ^\n",
- "SyntaxError: invalid syntax\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "def f(x, y,):\n",
- " print(x, y)\n",
- "\n",
- "def g(x=4, y=5,):\n",
- " print(x, y)\n",
- "\n",
- "def h(x, **kwargs,):\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " File \"\", line 1\n",
- " def h(*args,):\n",
- " ^\n",
- "SyntaxError: invalid syntax\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "def h(*args,):\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "\n",
- "- 在Python函数的形式参数列表中, 尾随逗号并不一定是合法的.\n",
- "- 在Python中, 参数列表部分用前置逗号定义, 部分用尾随逗号定义. 这种冲突导致逗号被夹在中间, 没有规则定义它.(译:这一句看得我也很懵逼,只能强翻了.详细解释看下面的讨论帖会一目了然.)\n",
- "- **注意:** 尾随逗号的问题已经在Python 3.6中被[修复](https://bugs.python.org/issue9232)了. 而这篇[帖子](https://bugs.python.org/issue9232#msg248399)中则简要讨论了Python中尾随逗号的不同用法.\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Strings and the backslashes/字符串与反斜杠\n",
- "**Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\"\n",
- "\n"
- ]
- }
- ],
- "source": [
- "print(\"\\\"\")\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\\\"\n",
- "\n"
- ]
- }
- ],
- "source": [
- "print(r\"\\\"\")\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "File \"\", line 1\n",
- " print(r\"\\\")\n",
- " ^\n",
- "SyntaxError: EOL while scanning string literal\n",
- "\n"
- ]
- }
- ],
- "source": [
- "print(r\"\\\")\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "r'\\'' == \"\\\\'\"\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "\n",
- "- 在一般的python字符串中,反斜杠用于转义可能具有特殊含义的字符(如单引号、双引号和反斜杠本身)。\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " 'wt\"f'\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " \"wt\\\"f\"\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "- 在以 `r` 开头的原始字符串中, 反斜杠并没有特殊含义.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " r'wt\\\"f' == 'wt\\\\\"f'\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " 'wt\\\\\"f'\n",
- "\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " print(repr(r'wt\\\"f')\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " print(\"\\n\")\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " '\\\\n'\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " print(r\"\\\\n\")\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "- 这意味着当解析器在原始字符串中遇到反斜杠时,它期望后面有另一个字符。 在我们的例子中(`print(r\"\\\")`),反斜杠转义了尾随引号,使解析器没有终止引号(因此产生了`SyntaxError`)。 这就是为什么反斜杠在原始字符串末尾不起作用的原因。\n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > not knot!/别纠结!\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "x = True\n",
- "y = False\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "not x == y\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " File \"\", line 1\n",
- " x == not y\n",
- " ^\n",
- "SyntaxError: invalid syntax\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "x == not y\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "\n",
- "* 运算符的优先级会影响表达式的求值顺序, 而在 Python 中 `==` 运算符的优先级要高于 `not` 运算符.\n",
- "* 所以 `not x == y` 相当于 `not (x == y)`, 同时等价于 `not (True == False)`, 最后的运算结果就是 `True`.\n",
- "* 之所以 `x == not y` 会抛一个 `SyntaxError` 异常, 是因为它会被认为等价于 `(x == not) y`, 而不是你一开始期望的 `x == (not y)`.\n",
- "* 解释器期望 `not` 标记是 `not in` 操作符的一部分 (因为 `==` 和 `not in` 操作符具有相同的优先级), 但是它在 `not` 标记后面找不到 `in` 标记, 所以会抛出 `SyntaxError` 异常.\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Half triple-quoted strings/三个引号\n",
- "**Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "wtfpython\n"
- ]
- }
- ],
- "source": [
- "print('wtfpython''')\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "wtfpython\n"
- ]
- }
- ],
- "source": [
- "print(\"wtfpython\"\"\")\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 下面的语句会抛出 `SyntaxError` 异常\n",
- "# print('''wtfpython')\n",
- "# print(\"\"\"wtfpython\")\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "+ Python 提供隐式的[字符串连接](https://docs.python.org/2/reference/lexical_analysis.html#string-literal-concatenation), 例如,\n",
- " ```\n",
- " >>> print(\"wtf\" \"python\")\n",
- " wtfpython\n",
- " >>> print(\"wtf\" \"\") # or \"wtf\"\"\"\n",
- " wtf\n",
- " ```\n",
- "+ `'''` 和 `\"\"\"` 在 Python中也是字符串定界符, Python 解释器在先遇到三个引号的的时候会尝试再寻找三个终止引号作为定界符, 如果不存在则会导致 `SyntaxError` 异常.\n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > What's wrong with booleans?/布尔你咋了?\n",
- "1\\.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 一个简单的例子, 统计下面可迭代对象中的布尔型值的个数和整型值的个数\n",
- "mixed_list = [False, 1.0, \"some_string\", 3, True, [], False]\n",
- "integers_found_so_far = 0\n",
- "booleans_found_so_far = 0\n",
- "\n",
- "for item in mixed_list:\n",
- " if isinstance(item, int):\n",
- " integers_found_so_far += 1\n",
- " elif isinstance(item, bool):\n",
- " booleans_found_so_far += 1\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "4\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "integers_found_so_far\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "0\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "booleans_found_so_far\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "2\\.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "'wtf'\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "some_bool = True\n",
- "\"wtf\" * some_bool\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "''\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "some_bool = False\n",
- "\"wtf\" * some_bool\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "3\\.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "def tell_truth():\n",
- " True = False\n",
- " if True == False:\n",
- " print(\"I have lost faith in truth!\")\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output (< 3.x):**\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "I have lost faith in truth!\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "tell_truth()\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "\n",
- "* 布尔值是 `int` 的子类\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " issubclass(bool, int)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " False\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " issubclass(int, bool)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "* 因此,`True` 和 `False` 是 `int` 的实例\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " isinstance(True, int)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " isinstance(False, int)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "* `True` 的整数值是 `1`, 而 `False` 的整数值是 `0`\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " 1\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " int(True)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " 0\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " int(False)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "* 关于其背后的原理, 请看这个 StackOverflow 的[回答](https://stackoverflow.com/a/8169049/4354153).\n",
- "\n",
- "* 最初,Python 没有 `bool` 类型(人们使用 0 表示假,使用非零值,如 1 表示真)。`True`、`False` 和 `bool` 类型在 2.x 版本中被添加,但为了向后兼容,`True` 和 `False` 不能成为常量。它们只是内置变量,可以重新分配它们\n",
- "\n",
- "* Python 3 向后不兼容,问题终于得到解决,因此最后一个代码段不适用于 Python 3.x!\n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Class attributes and instance attributes/类属性和实例属性\n",
- "1\\.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "class A:\n",
- " x = 1\n",
- "\n",
- "class B(A):\n",
- " pass\n",
- "\n",
- "class C(A):\n",
- " pass\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "(1, 1, 1)\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A.x, B.x, C.x\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "(1, 2, 1)\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "B.x = 2\n",
- "A.x, B.x, C.x\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "(3, 2, 3)\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A.x = 3\n",
- "A.x, B.x, C.x\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "(3, 3)\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "a = A()\n",
- "a.x, A.x\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "(4, 3)\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "a.x += 1\n",
- "a.x, A.x\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "2\\.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "class SomeClass:\n",
- " some_var = 15\n",
- " some_list = [5]\n",
- " another_list = [5]\n",
- " def __init__(self, x):\n",
- " self.some_var = x + 1\n",
- " self.some_list = self.some_list + [x]\n",
- " self.another_list += [x]\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "[5, 420]\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "some_obj = SomeClass(420)\n",
- "some_obj.some_list\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "[5, 420]\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "some_obj.another_list\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "[5, 111]\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "another_obj = SomeClass(111)\n",
- "another_obj.some_list\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "[5, 420, 111]\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "another_obj.another_list\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "another_obj.another_list is SomeClass.another_list\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "another_obj.another_list is some_obj.another_list\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "\n",
- "* 类变量和实例变量在内部是通过类对象的字典来处理(译: 就是 `__dict__` 属性). 如果在当前类的字典中找不到的话就去它的父类中寻找.\n",
- "* `+=` 运算符会在原地修改可变对象, 而不是创建新对象. 因此, 在这种情况下, 修改一个实例的属性会影响其他实例和类属性.\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > yielding None/生成 None\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "some_iterable = ('a', 'b')\n",
- "\n",
- "def some_func(val):\n",
- " return \"something\"\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "['a', 'b']\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "[x for x in some_iterable]\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " at 0x7f70b0a4ad58>\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "[(yield x) for x in some_iterable]\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "['a', 'b']\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "list([(yield x) for x in some_iterable])\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "['a', None, 'b', None]\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "list((yield x) for x in some_iterable)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "['a', 'something', 'b', 'something']\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "list(some_func((yield x)) for x in some_iterable)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "- 来源和解释可以在这里找到: https://stackoverflow.com/questions/32139885/yield-in-list-comprehensions-and-generator-expressions\n",
- "- 相关错误报告: http://bugs.python.org/issue10544\n",
- "- 这个bug在3.7以后的版本中不被推荐使用, 并在3.8中被修复. 因此在3.8中尝试在推导式中使用 yield, 只会得到一个 SyntaxError. 详细内容可以看[3.7更新内容](https://docs.python.org/dev/whatsnew/3.7.html#deprecated-python-behavior), [3.8更新内容](https://docs.python.org/dev/whatsnew/3.8.html#changes-in-python-behavior).\n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Yielding from... return!/生成器里的return *\n",
- "1\\.\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "def some_func(x):\n",
- " if x == 3:\n",
- " return [\"wtf\"]\n",
- " else:\n",
- " yield from range(x)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output (> 3.3):**\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "[]\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "list(some_func(3))\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "`\"wtf\"` 去哪儿了?是因为`yield from`的一些特殊效果吗?让我们验证一下\n",
- "\n",
- "2\\.\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "def some_func(x):\n",
- " if x == 3:\n",
- " return [\"wtf\"]\n",
- " else:\n",
- " for i in range(x):\n",
- " yield i\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "[]\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "list(some_func(3))\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "同样的结果,这里也不起作用。\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明\n",
- "\n",
- "+ 从 Python 3.3 开始,可以在生成器中使用带有值的 `return` 语句(参见 [PEP380](https://www.python.org/dev/peps/pep-0380/))。 [官方文档](https://www.python.org/dev/peps/pep-0380/#enhancements-to-stopiteration) 描述,\n",
- "\n",
- "> \"... 生成器中的 `return expr` 会导致在退出生成器时引发 `StopIteration(expr)`。\"\n",
- "\n",
- "+ 在 `some_func(3)` 例子中,`return` 语句在开始就引发了`StopIteration`。 `StopIteration` 异常会在`list(...)` 包装器和`for` 循环中自动捕获。 因此,以上两个片段都产生的是一个空列表。\n",
- "\n",
- "+ 要从生成器 `some_func` 中获取 `[\"wtf\"]`,我们需要捕获 `StopIteration` 异常,\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " try:\n",
- " next(some_func(3))\n",
- " except StopIteration as e:\n",
- " some_string = e.value\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " [\"wtf\"]\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " some_string\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Nan-reflexivity/Nan的自反性\n",
- "1\\.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "a = float('inf')\n",
- "b = float('nan')\n",
- "c = float('-iNf') # 这些字符串不区分大小写\n",
- "d = float('nan')\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "inf\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "a\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "nan\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "b\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "-inf\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "c\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "ValueError: could not convert string to float: some_other_string\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "float('some_other_string')\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "a == -c #inf==inf\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "None == None # None==None\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "False\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "b == d #但是 nan!=nan\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "0.0\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "50/a\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "nan\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "a/a\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "nan\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "23 + b\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "2\\.\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "x = float('nan')\n",
- "y = x / x\n",
- "y is y # 同一性(identity)具备\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "False\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "y == y # y不具备相等性(equality)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "[y] == [y] # 但包含y的列表验证相等性(equality)成功了\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "\n",
- "`'inf'` 和 `'nan'` 是特殊的字符串(不区分大小写), 当显示转换成 `float` 型时, 它们分别用于表示数学意义上的 \"无穷大\" 和 \"非数字\".\n",
- "- 由于根据 IEEE 标准 `NaN != NaN`,遵守此规则打破了 Python 中集合元素的自反性假设,即如果 `x` 是 `list` 等集合的一部分,则比较等运算的实现基于假设`x == x`。由于这个假设,在比较两个元素时首先比较身份`identity`(因为它更快),并且仅在身份不匹配时才比较值。以下片段将更清楚地说明,\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " (False, True)\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " x = float('nan')\n",
- " x == x, [x] == [x]\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " (False, True)\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " y = float('nan')\n",
- " y == y, [y] == [y]\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " (False, False)\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " x == y, [x] == [y]\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- " 由于 `x` 和 `y` 的身份`identity`不同,所以考虑的值也不同; 因此这次比较返回“False”。\n",
- "\n",
- "\n",
- "- 感兴趣可以阅读 [Reflexivity, and other pillars of civilization](https://bertrandmeyer.com/2010/02/06/reflexivity-and-other-pillars-of-civilization/)\n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Mutating the immutable!/强人所难\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "some_tuple = (\"A\", \"tuple\", \"with\", \"values\")\n",
- "another_tuple = ([1, 2], [3, 4], [5, 6])\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "TypeError: 'tuple' object does not support item assignment\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "some_tuple[2] = \"change this\"\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "([1, 2], [3, 4], [5, 6, 1000])\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "another_tuple[2].append(1000) # 这里不出现错误\n",
- "another_tuple\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "TypeError: 'tuple' object does not support item assignment\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "another_tuple[2] += [99, 999]\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "([1, 2], [3, 4], [5, 6, 1000, 99, 999])\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "another_tuple\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "我还以为元组是不可变的呢...\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "\n",
- "* 引用 https://docs.python.org/2/reference/datamodel.html\n",
- "\n",
- " > 不可变序列\n",
- " 不可变序列的对象一旦创建就不能再改变. (如果对象包含对其他对象的引用,则这些其他对象可能是可变的并且可能会被修改; 但是,由不可变对象直接引用的对象集合不能更改.)\n",
- "\n",
- "* `+=` 操作符在原地修改了列表. 元素赋值操作并不工作, 但是当异常抛出时, 元素已经在原地被修改了.\n",
- "\n",
- "(译: 对于不可变对象, 这里指tuple, `+=` 并不是原子操作, 而是 `extend` 和 `=` 两个动作, 这里 `=` 操作虽然会抛出异常, 但 `extend` 操作已经修改成功了. 详细解释可以看[这里](https://segmentfault.com/a/1190000010767068))\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > The disappearing variable from outer scope/消失的外部变量\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "e = 7\n",
- "try:\n",
- " raise Exception()\n",
- "except Exception as e:\n",
- " pass\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output (Python 2.x):**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "# prints nothing\n"
- ]
- }
- ],
- "source": [
- "print(e)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output (Python 3.x):**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "NameError: name 'e' is not defined\n"
- ]
- }
- ],
- "source": [
- "print(e)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "\n",
- "* 出处: https://docs.python.org/3/reference/compound_stmts.html#except\n",
- "\n",
- " 当使用 `as` 为目标分配异常的时候, 将在except子句的末尾清除该异常.\n",
- "\n",
- " 这就好像\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " except E as N:\n",
- " foo\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- " 会被翻译成\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " except E as N:\n",
- " try:\n",
- " foo\n",
- " finally:\n",
- " del N\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- " 这意味着异常必须在被赋值给其他变量才能在 `except` 子句之后引用它. 而异常之所以会被清除, 则是由于上面附加的回溯信息(trackback)会和栈帧(stack frame)形成循环引用, 使得该栈帧中的所有本地变量在下一次垃圾回收发生之前都处于活动状态.(译: 也就是说不会被回收)\n",
- "\n",
- "* 子句在 Python 中并没有独立的作用域. 示例中的所有内容都处于同一作用域内, 所以变量 `e` 会由于执行了 `except` 子句而被删除. 而对于有独立的内部作用域的函数来说情况就不一样了. 下面的例子说明了这一点:\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " def f(x):\n",
- " del(x)\n",
- " print(x)\n",
- "\n",
- " x = 5\n",
- " y = [5, 4, 3]\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- " **Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " 5\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " >>>f(x)\n",
- " UnboundLocalError: local variable 'x' referenced before assignment\n",
- " >>>f(y)\n",
- " UnboundLocalError: local variable 'x' referenced before assignment\n",
- " x\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " [5, 4, 3]\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " y\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "* 在 Python 2.x 中, `Exception()` 实例被赋值给了变量 `e`, 所以当你尝试打印结果的时候, 它的输出为空.(译: 正常的Exception实例打印出来就是空)\n",
- "\n",
- " **Output (Python 2.x):**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " Exception()\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " e\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " # 没有打印任何内容!\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " print e\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > The mysterious key type conversion/神秘的键型转换 *\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "class SomeClass(str):\n",
- " pass\n",
- "\n",
- "some_dict = {'s':42}\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "str\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "type(list(some_dict.keys())[0])\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "{'s': 40}\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "s = SomeClass('s')\n",
- "some_dict[s] = 40\n",
- "some_dict # 预期: 两个不同的键值对\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "str\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "type(list(some_dict.keys())[0])\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "\n",
- "* 由于 `SomeClass` 会从 `str` 自动继承 `__hash__` 方法, 所以 `s` 对象和 `\"s\"` 字符串的哈希值是相同的.\n",
- "* 而 `SomeClass(\"s\") == \"s\"` 为 `True` 是因为 `SomeClass` 也继承了 `str` 类 `__eq__` 方法.\n",
- "* 由于两者的哈希值相同且相等, 所以它们在字典中表示相同的键.\n",
- "* 如果想要实现期望的功能, 我们可以重定义 `SomeClass` 的 `__eq__` 方法.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " class SomeClass(str):\n",
- " def __eq__(self, other):\n",
- " return (\n",
- " type(self) is SomeClass\n",
- " and type(other) is SomeClass\n",
- " and super().__eq__(other)\n",
- " )\n",
- "\n",
- " # 当我们自定义 __eq__ 方法时, Python 不会再自动继承 __hash__ 方法\n",
- " # 所以我们也需要定义它\n",
- " __hash__ = str.__hash__\n",
- "\n",
- " some_dict = {'s':42}\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- " **Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " {'s': 40, 's': 42}\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " s = SomeClass('s')\n",
- " some_dict[s] = 40\n",
- " some_dict\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " (__main__.SomeClass, str)\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " keys = list(some_dict.keys())\n",
- " type(keys[0]), type(keys[1])\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Let's see if you can guess this?/看看你能否猜到这一点?\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "a, b = a[b] = {}, 5\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "{5: ({...}, 5)}\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "a\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "\n",
- "* 根据 [Python 语言参考](https://docs.python.org/2/reference/simple_stmts.html#assignment-statements), 赋值语句的形式如下\n",
- " ```\n",
- " (target_list \"=\")+ (expression_list | yield_expression)\n",
- " ```\n",
- "\n",
- " > 赋值语句计算表达式列表(expression list)(牢记 这可以是单个表达式或以逗号分隔的列表, 后者返回元组)并将单个结果对象从左到右分配给目标列表中的每一项.\n",
- "\n",
- "* `(target_list \"=\")+` 中的 `+` 意味着可以有**一个或多个**目标列表. 在这个例子中, 目标列表是 `a, b` 和 `a[b]` (注意表达式列表只能有一个, 在我们的例子中是 `{}, 5`).\n",
- "\n",
- "* 表达式列表计算结束后, 将其值自动解包后**从左到右**分配给目标列表(target list). 因此, 在我们的例子中, 首先将 `{}, 5` 元组并赋值给 `a, b`, 然后我们就可以得到 `a = {}` 且 `b = 5`.\n",
- "\n",
- "* `a` 被赋值的 `{}` 是可变对象.\n",
- "\n",
- "* 第二个目标列表是 `a[b]` (你可能觉得这里会报错, 因为在之前的语句中 `a` 和 `b` 都还没有被定义. 但是别忘了, 我们刚刚将 `a` 赋值 `{}` 且将 `b` 赋值为 `5`).\n",
- "\n",
- "* 现在, 我们将通过将字典中键 `5` 的值设置为元组 `({}, 5)` 来创建循环引用 (输出中的 `{...}` 指与 `a` 引用了相同的对象). 下面是一个更简单的循环引用的例子\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " [[...]]\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " some_list = some_list[0] = [0]\n",
- " some_list\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " [[...]]\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " some_list[0]\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " some_list is some_list[0]\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " some_list[0][0][0][0][0][0] == some_list\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- " 我们的例子就是这种情况 (`a[b][0]` 与 `a` 是相同的对象)\n",
- "\n",
- "* 总结一下, 你也可以把例子拆成\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " a, b = {}, 5\n",
- " a[b] = a, b\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- " 并且可以通过 `a[b][0]` 与 `a` 是相同的对象来证明是循环引用\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " a[b][0] is a\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Modifying a dictionary while iterating over it/迭代字典时的修改\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "x = {0: None}\n",
- "\n",
- "for i in x:\n",
- " del x[i]\n",
- " x[i+1] = None\n",
- " print(i)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output (Python 2.7- Python 3.5):**\n",
- "\n",
- "```\n",
- "0\n",
- "1\n",
- "2\n",
- "3\n",
- "4\n",
- "5\n",
- "6\n",
- "7\n",
- "```\n",
- "\n",
- "是的, 它运行了**八次**然后才停下来.\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "\n",
- "* Python不支持对字典进行迭代的同时修改它.\n",
- "* 它之所以运行8次, 是因为字典会自动扩容以容纳更多键值(我们有8次删除记录, 因此需要扩容). 这实际上是一个实现细节. (译: 应该是因为字典的初始最小值是8, 扩容会导致散列表地址发生变化而中断循环.)\n",
- "* 在不同的Python实现中删除键的处理方式以及调整大小的时间可能会有所不同.(译: 就是说什么时候扩容在不同版本中可能是不同的, 在3.6及3.7的版本中到[5](https://github.com/python/cpython/blob/v3.6.1/Objects/dictobject.c#L103-L110)就会自动扩容了. 以后也有可能再次发生变化. 这是为了避免散列冲突. 顺带一提, 后面两次扩容会扩展为32和256. 即`8->32->256`.)\n",
- "* 更多的信息, 你可以参考这个StackOverflow的[回答](https://stackoverflow.com/questions/44763802/bug-in-python-dict), 它详细的解释一个类似的例子.\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Stubborn `del` operator/坚强的 `del` *\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "class SomeClass:\n",
- " def __del__(self):\n",
- " print(\"Deleted!\")\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n",
- "1\\.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "Deleted!\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "x = SomeClass()\n",
- "y = x\n",
- "del x # 这里应该会输出 \"Deleted!\"\n",
- "del y\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "唷, 终于删除了. 你可能已经猜到了在我们第一次尝试删除 `x` 时是什么让 `__del__` 免于被调用的. 那让我们给这个例子增加点难度.\n",
- "\n",
- "2\\.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "<__main__.SomeClass instance at 0x7f98a1a67fc8>\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "x = SomeClass()\n",
- "y = x\n",
- "del x\n",
- "y # 检查一下y是否存在\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "Deleted!\n",
- "{'__builtins__': , 'SomeClass': , '__package__': None, '__name__': '__main__', '__doc__': None}\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "del y # 像之前一样, 这里应该会输出 \"Deleted!\"\n",
- "globals() # 好吧, 并没有. 让我们看一下所有的全局变量\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "好了,现在它被删除了 :confused:\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "+ `del x` 并不会立刻调用 `x.__del__()`.\n",
- "+ 每当遇到 `del x`, Python 会将 `x` 的引用数减1, 当 `x` 的引用数减到0时就会调用 `x.__del__()`.\n",
- "+ 在第二个例子中, `y.__del__()` 之所以未被调用, 是因为前一条语句 (`>>> y`) 对同一对象创建了另一个引用, 从而防止在执行 `del y` 后对象的引用数变为0.\n",
- "+ 调用 `globals` 导致引用被销毁, 因此我们可以看到 \"Deleted!\" 终于被输出了.\n",
- "+ (译: 这其实是 Python 交互解释器的特性, 它会自动让 `_` 保存上一个表达式输出的值, 详细可以看[这里](https://www.cnblogs.com/leisurelylicht/p/diao-pi-de-kong-zhi-tai.html).)\n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > The out of scope variable/外部作用域变量\n",
- "1\\.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "a = 1\n",
- "def some_func():\n",
- " return a\n",
- "\n",
- "def another_func():\n",
- " a += 1\n",
- " return a\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "2\\.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "def some_closure_func():\n",
- " a = 1\n",
- " def some_inner_func():\n",
- " return a\n",
- " return some_inner_func()\n",
- "\n",
- "def another_closure_func():\n",
- " a = 1\n",
- " def another_inner_func():\n",
- " a += 1\n",
- " return a\n",
- " return another_inner_func()\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "1\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "some_func()\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "UnboundLocalError: local variable 'a' referenced before assignment\n",
- "\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "another_func()\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "1\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "some_closure_func()\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "UnboundLocalError: local variable 'a' referenced before assignment\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "another_closure_func()\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "* 当你在作用域中对变量进行赋值时, 变量会变成该作用域内的局部变量. 因此 `a` 会变成 `another_func` 函数作用域中的局部变量, 但它在函数作用域中并没有被初始化, 所以会引发错误.\n",
- "* 想要在 `another_func` 中修改外部作用域变量 `a` 的话, 可以使用 `global` 关键字.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " def another_func()\n",
- " global a\n",
- " a += 1\n",
- " return a\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- " **Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " 2\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " another_func()\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "* 在 `another_closure_func` 函数中,`a` 会变成 `another_inner_func` 函数作用域中的局部变量, 但它在同一作用域中并没有被初始化, 所以会引发错误。\n",
- "* 想要在 `another_inner_func` 中修改外部作用域变量 `a` 的话, 可以使用 `nonlocal` 关键字。nonlocal 表达式用于(除全局作用域外)最近一级的外部作用域。\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " def another_func():\n",
- " a = 1\n",
- " def another_inner_func():\n",
- " nonlocal a\n",
- " a += 1\n",
- " return a\n",
- " return another_inner_func()\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- " **Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " 2\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " another_func()\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "* `global` and `nonlocal` 关键字告诉 `Python` 解释器,不要声明新变量,而是在相应的外部作用域中查找变量。\n",
- "* 可以阅读[这个](https://sebastianraschka.com/Articles/2014_python_scope_and_namespaces.html)简短却很棒的指南, 了解更多关于 Python 中命名空间和作用域的工作原理。\n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Deleting a list item while iterating/迭代列表时删除元素\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "list_1 = [1, 2, 3, 4]\n",
- "list_2 = [1, 2, 3, 4]\n",
- "list_3 = [1, 2, 3, 4]\n",
- "list_4 = [1, 2, 3, 4]\n",
- "\n",
- "for idx, item in enumerate(list_1):\n",
- " del item\n",
- "\n",
- "for idx, item in enumerate(list_2):\n",
- " list_2.remove(item)\n",
- "\n",
- "for idx, item in enumerate(list_3[:]):\n",
- " list_3.remove(item)\n",
- "\n",
- "for idx, item in enumerate(list_4):\n",
- " list_4.pop(idx)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "[1, 2, 3, 4]\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "list_1\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "[2, 4]\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "list_2\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "[]\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "list_3\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "[2, 4]\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "list_4\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "你能猜到为什么输出是 `[2, 4]` 吗?\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "\n",
- "* 在迭代时修改对象是一个很愚蠢的主意. 正确的做法是迭代对象的副本, `list_3[:]` 就是这么做的.\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " 139798789457608\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " some_list = [1, 2, 3, 4]\n",
- " id(some_list)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " 139798779601192\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " id(some_list[:]) # 注意python为切片列表创建了新对象.\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**`del`, `remove` 和 `pop` 的不同:**\n",
- "* `del var_name` 只是从本地或全局命名空间中删除了 `var_name` (这就是为什么 `list_1` 没有受到影响).\n",
- "* `remove` 会删除第一个匹配到的指定值, 而不是特定的索引, 如果找不到值则抛出 `ValueError` 异常.\n",
- "* `pop` 则会删除指定索引处的元素并返回它, 如果指定了无效的索引则抛出 `IndexError` 异常.\n",
- "\n",
- "**为什么输出是 `[2, 4]`?**\n",
- "- 列表迭代是按索引进行的, 所以当我们从 `list_2` 或 `list_4` 中删除 `1` 时, 列表的内容就变成了 `[2, 3, 4]`. 剩余元素会依次位移, 也就是说, `2` 的索引会变为 0, `3` 会变为 1. 由于下一次迭代将获取索引为 1 的元素 (即 `3`), 因此 `2` 将被彻底的跳过. 类似的情况会交替发生在列表中的每个元素上.\n",
- "\n",
- "* 参考这个StackOverflow的[回答](https://stackoverflow.com/questions/45946228/what-happens-when-you-try-to-delete-a-list-element-while-iterating-over-it)来解释这个例子\n",
- "* 关于Python中字典的类似例子, 可以参考这个Stackoverflow的[回答](https://stackoverflow.com/questions/45877614/how-to-change-all-the-dictionary-keys-in-a-for-loop-with-d-items).\n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Lossy zip of iterators/丢三落四的zip *\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "[0, 1, 2, 3, 4, 5, 6]\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "numbers = list(range(7))\n",
- "numbers\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "([0, 1, 2], [3, 4, 5, 6])\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "first_three, remaining = numbers[:3], numbers[3:]\n",
- "first_three, remaining\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "[(0, 0), (1, 1), (2, 2)]\n",
- "# so far so good, let's zip the remaining\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "numbers_iter = iter(numbers)\n",
- "list(zip(numbers_iter, first_three)) \n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "[(4, 3), (5, 4), (6, 5)]\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "list(zip(numbers_iter, remaining))\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "`numbers` 列表中的元素 `3` 哪里去了?\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明\n",
- "\n",
- "- 根据Python [文档](https://docs.python.org/3.3/library/functions.html#zip), `zip` 函数的大概实现如下:\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " def zip(*iterables):\n",
- " sentinel = object()\n",
- " iterators = [iter(it) for it in iterables]\n",
- " while iterators:\n",
- " result = []\n",
- " for it in iterators:\n",
- " elem = next(it, sentinel)\n",
- " if elem is sentinel: return\n",
- " result.append(elem)\n",
- " yield tuple(result)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "- 该函数接受任意数量的可迭代对象,通过调用 `next` 函数将它们的每个项目添加到 `result` 列表中,并在任一可迭代对象耗尽时停止。\n",
- "- 这里需要注意的是,当任一可迭代对象用尽时,`result` 列表中的现有元素将被丢弃。这就是 `numbers_iter` 中的 `3` 所发生的情况。\n",
- "- 使用 zip 执行上述操作的正确方法是:\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " [(0, 0), (1, 1), (2, 2)]\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " numbers = list(range(7))\n",
- " numbers_iter = iter(numbers)\n",
- " list(zip(first_three, numbers_iter))\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " [(3, 3), (4, 4), (5, 5), (6, 6)]\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " list(zip(remaining, numbers_iter))\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- " `zip` 的第一个参数应当是有最少元素的那个。\n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Loop variables leaking out!/循环变量泄漏!\n",
- "1\\.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": []
- }
- ],
- "source": [
- "for x in range(7):\n",
- " if x == 6:\n",
- " print(x, ': for x inside loop')\n",
- "print(x, ': x in global')\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "6 : for x inside loop\n",
- "6 : x in global\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "但是 `x` 从未在循环外被定义...\n",
- "\n",
- "2\\.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": []
- }
- ],
- "source": [
- "# 这次我们先初始化x\n",
- "x = -1\n",
- "for x in range(7):\n",
- " if x == 6:\n",
- " print(x, ': for x inside loop')\n",
- "print(x, ': x in global')\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "6 : for x inside loop\n",
- "6 : x in global\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "3\\.\n",
- "```\n",
- "x = 1\n",
- "print([x for x in range(5)])\n",
- "print(x, ': x in global')\n",
- "```\n",
- "\n",
- "**Output (on Python 2.x):**\n",
- "```\n",
- "[0, 1, 2, 3, 4]\n",
- "(4, ': x in global')\n",
- "```\n",
- "\n",
- "**Output (on Python 3.x):**\n",
- "```\n",
- "[0, 1, 2, 3, 4]\n",
- "1 : x in global\n",
- "```\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "\n",
- "- 在 Python 中, for 循环使用所在作用域并在结束后保留定义的循环变量. 如果我们曾在全局命名空间中定义过循环变量. 在这种情况下, 它会重新绑定现有变量.\n",
- "\n",
- "- Python 2.x 和 Python 3.x 解释器在列表推导式示例中的输出差异, 在文档 [What’s New In Python 3.0](https://docs.python.org/3/whatsnew/3.0.html) 中可以找到相关的解释:\n",
- "\n",
- " > \"列表推导不再支持句法形式 `[... for var in item1, item2, ...]`. 取而代之的是 `[... for var in (item1, item2, ...)]`. 另外, 注意列表推导具有不同的语义: 它们更接近于 `list()` 构造函数中生成器表达式的语法糖(译: 这一句我也不是很明白), 特别是循环控制变量不再泄漏到周围的作用域中.\"\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Beware of default mutable arguments!/当心默认的可变参数!\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "def some_func(default_arg=[]):\n",
- " default_arg.append(\"some_string\")\n",
- " return default_arg\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "['some_string']\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "some_func()\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "['some_string', 'some_string']\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "some_func()\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "['some_string']\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "some_func([])\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "['some_string', 'some_string', 'some_string']\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "some_func()\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "\n",
- "- Python中函数的默认可变参数并不是每次调用该函数时都会被初始化. 相反, 它们会使用最近分配的值作为默认值. 当我们明确的将 `[]` 作为参数传递给 `some_func` 的时候, 就不会使用 `default_arg` 的默认值, 所以函数会返回我们所期望的结果.\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " def some_func(default_arg=[]):\n",
- " default_arg.append(\"some_string\")\n",
- " return default_arg\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- " **Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " ([],)\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " some_func.__defaults__ # 这里会显示函数的默认参数的值\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " (['some_string'],)\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " some_func()\n",
- " some_func.__defaults__\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " (['some_string', 'some_string'],)\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " some_func()\n",
- " some_func.__defaults__\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " (['some_string', 'some_string'],)\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " some_func([])\n",
- " some_func.__defaults__\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "- 避免可变参数导致的错误的常见做法是将 `None` 指定为参数的默认值, 然后检查是否有值传给对应的参数. 例:\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " def some_func(default_arg=None):\n",
- " if not default_arg:\n",
- " default_arg = []\n",
- " default_arg.append(\"some_string\")\n",
- " return default_arg\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Catching the Exceptions/捕获异常\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "some_list = [1, 2, 3]\n",
- "try:\n",
- " # 这里会抛出异常 ``IndexError``\n",
- " print(some_list[4])\n",
- "except IndexError, ValueError:\n",
- " print(\"Caught!\")\n",
- "\n",
- "try:\n",
- " # 这里会抛出异常 ``ValueError``\n",
- " some_list.remove(4)\n",
- "except IndexError, ValueError:\n",
- " print(\"Caught again!\")\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output (Python 2.x):**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "Caught!\n",
- "\n",
- "ValueError: list.remove(x): x not in list\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output (Python 3.x):**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " File \"\", line 3\n",
- " except IndexError, ValueError:\n",
- " ^\n",
- "SyntaxError: invalid syntax\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "\n",
- "* 如果你想要同时捕获多个不同类型的异常时, 你需要将它们用括号包成一个元组作为第一个参数传递. 第二个参数是可选名称, 如果你提供, 它将与被捕获的异常实例绑定. 例,\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " some_list = [1, 2, 3]\n",
- " try:\n",
- " # 这里会抛出异常 ``ValueError``\n",
- " some_list.remove(4)\n",
- " except (IndexError, ValueError), e:\n",
- " print(\"Caught again!\")\n",
- " print(e)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- " **Output (Python 2.x):**\n",
- " ```\n",
- " Caught again!\n",
- " list.remove(x): x not in list\n",
- " ```\n",
- " **Output (Python 3.x):**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " File \"\", line 4\n",
- " except (IndexError, ValueError), e:\n",
- " ^\n",
- " IndentationError: unindent does not match any outer indentation level\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "* 在 Python 3 中, 用逗号区分异常与可选名称是无效的; 正确的做法是使用 `as` 关键字. 例,\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " some_list = [1, 2, 3]\n",
- " try:\n",
- " some_list.remove(4)\n",
- "\n",
- " except (IndexError, ValueError) as e:\n",
- " print(\"Caught again!\")\n",
- " print(e)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- " **Output:**\n",
- " ```\n",
- " Caught again!\n",
- " list.remove(x): x not in list\n",
- " ```\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Same operands, different story!/同人不同命!\n",
- "1\\.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "a = [1, 2, 3, 4]\n",
- "b = a\n",
- "a = a + [5, 6, 7, 8]\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "[1, 2, 3, 4, 5, 6, 7, 8]\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "a\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "[1, 2, 3, 4]\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "b\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "2\\.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "a = [1, 2, 3, 4]\n",
- "b = a\n",
- "a += [5, 6, 7, 8]\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "[1, 2, 3, 4, 5, 6, 7, 8]\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "a\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "[1, 2, 3, 4, 5, 6, 7, 8]\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "b\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "\n",
- "* `a += b` 并不总是与 `a = a + b` 表现相同. 类实现 *`op=`* 运算符的方式 *也许* 是不同的, 列表就是这样做的.\n",
- "\n",
- "* 表达式 `a = a + [5,6,7,8]` 会生成一个新列表, 并让 `a` 引用这个新列表, 同时保持 `b` 不变.\n",
- "\n",
- "* 表达式 `a += [5,6,7,8]` 实际上是使用的是 \"extend\" 函数, 所以 `a` 和 `b` 仍然指向已被修改的同一列表.\n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Name resolution ignoring class scope/忽略类作用域的名称解析\n",
- "1\\.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "x = 5\n",
- "class SomeClass:\n",
- " x = 17\n",
- " y = (x for i in range(10))\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "5\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "list(SomeClass.y)[0]\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "2\\.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "x = 5\n",
- "class SomeClass:\n",
- " x = 17\n",
- " y = [x for i in range(10)]\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output (Python 2.x):**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "17\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "SomeClass.y[0]\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output (Python 3.x):**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "5\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "SomeClass.y[0]\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "- 类定义中嵌套的作用域会忽略类内的名称绑定.\n",
- "- 生成器表达式有它自己的作用域.\n",
- "- 从 Python 3.X 开始, 列表推导式也有自己的作用域.\n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Rounding like a banker/像银行家一样舍入 *\n",
- "让我们实现一个简单的函数来获取列表的中间元素:\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "def get_middle(some_list):\n",
- " mid_index = round(len(some_list) / 2)\n",
- " return some_list[mid_index - 1]\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Python 3.x:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "1\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "get_middle([1]) # looks good\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "2\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "get_middle([1,2,3]) # looks good\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "2\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "get_middle([1,2,3,4,5]) # huh?\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "2.5\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "len([1,2,3,4,5]) / 2 # good\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "2\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "round(len([1,2,3,4,5]) / 2) # why?\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "似乎 Python 将 2.5 舍入到 2。\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明\n",
- "\n",
- "- - 这不是浮点精度错误,实际上,这种行为是故意的。从 Python 3.0 开始,`round()` 使用[银行进位法](https://en.wikipedia.org/wiki/Rounding#Round_half_to_even),其中 0.5 小数四舍五入到最接近的 **偶数** :\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "0\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "round(0.5)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "2\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "round(1.5)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "2\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "round(2.5)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "0.0\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "import numpy # numpy的结果也是一样\n",
- "numpy.round(0.5)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "2.0\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "numpy.round(1.5)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "2.0\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "numpy.round(2.5)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "- 这是 [IEEE 754](https://en.wikipedia.org/wiki/IEEE_754#Rounding_rules) 中描述的关于0.5分位舍入的推荐方法。然而,另一种方法(从零取整)大部分时间都是在学校教授的,所以银行进位法可能并不为人所知。此外,一些最流行的编程语言(例如:JavaScript、Java、C/C++、Ruby、Rust)也不使用银行进位法。因此,这对 Python 来说还是比较特殊的,在四舍五入时可能会导致混淆。\n",
- "- 了解更多信息,请参阅文档 [round()](https://docs.python.org/3/library/functions.html#round) 或 [this stackoverflow thread](https://stackoverflow.com/questions/10825926/python -3-x-rounding-behavior) \n",
- "- 请注意,`get_middle([1])` 只返回1,因为它的索引是 `round(0.5) - 1 = 0 - 1 = -1`,返回列表中的最后一个元素。\n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Needles in a Haystack/大海捞针\n",
- "迄今为止,每一位Python开发者都会遇到类似以下的情况。\n",
- "\n",
- "1\\.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "x, y = (0, 1) if True else None, None\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n",
- "```\n",
- ">>> x, y # 期望的结果是 (0, 1)\n",
- "((0, 1), None)\n",
- "```\n",
- "\n",
- "2\\.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": []
- }
- ],
- "source": [
- "t = ('one', 'two')\n",
- "for i in t:\n",
- " print(i)\n",
- "\n",
- "t = ('one')\n",
- "for i in t:\n",
- " print(i)\n",
- "\n",
- "t = ()\n",
- "print(t)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "one\n",
- "two\n",
- "o\n",
- "n\n",
- "e\n",
- "tuple()\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "3\\.\n",
- "\n",
- "```\n",
- "ten_words_list = [\n",
- " \"some\",\n",
- " \"very\",\n",
- " \"big\",\n",
- " \"list\",\n",
- " \"that\"\n",
- " \"consists\",\n",
- " \"of\",\n",
- " \"exactly\",\n",
- " \"ten\",\n",
- " \"words\"\n",
- "]\n",
- "```\n",
- "\n",
- "**Output**\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "9\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "len(ten_words_list)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "4\\. 不够健壮的断言机制\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "a = \"python\"\n",
- "b = \"javascript\"\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "# 未引发 AssertionError \n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 带有失败警告信息的assert表达式\n",
- "assert(a == b, \"Both languages are different\")\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "5\\.\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "some_list = [1, 2, 3]\n",
- "some_dict = {\n",
- " \"key_1\": 1,\n",
- " \"key_2\": 2,\n",
- " \"key_3\": 3\n",
- "}\n",
- "\n",
- "some_list = some_list.append(4) \n",
- "some_dict = some_dict.update({\"key_4\": 4})\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "None\n"
- ]
- }
- ],
- "source": [
- "print(some_list)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "None\n"
- ]
- }
- ],
- "source": [
- "print(some_dict)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "6\\.\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "def some_recursive_func(a):\n",
- " if a[0] == 0:\n",
- " return\n",
- " a[0] -= 1\n",
- " some_recursive_func(a)\n",
- " return a\n",
- "\n",
- "def similar_recursive_func(a):\n",
- " if a == 0:\n",
- " return a\n",
- " a -= 1\n",
- " similar_recursive_func(a)\n",
- " return a\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "[0, 0]\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "some_recursive_func([5, 0])\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "4\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "similar_recursive_func(5)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "* 对于 1, 正确的语句是 `x, y = (0, 1) if True else (None, None)`.\n",
- "* 对于 2, 正确的语句是 `t = ('one',)` 或者 `t = 'one',` (缺少逗号) 否则解释器会认为 `t` 是一个字符串, 并逐个字符对其进行迭代.\n",
- "* `()` 是一个特殊的标记,表示空元组.\n",
- "* 对于 3,正如您可能已经弄清楚的那样,列表中的第5个元素(\"that\")后面缺少一个逗号。因此,通过隐式字符串字面连接,\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " ['some', 'very', 'big', 'list', 'thatconsists', 'of', 'exactly', 'ten', 'words']\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " ten_words_list\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "* 在第4个代码段中没有引发\"AssertionError\",因为我们不是断言单个表达式 `a == b`,而是断言整个元组。以下代码段将说明问题,\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " Traceback (most recent call last):\n",
- " File \"\", line 1, in \n",
- " AssertionError\n",
- " \n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " a = \"python\"\n",
- " b = \"javascript\"\n",
- " assert a == b\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " :1: SyntaxWarning: assertion is always true, perhaps remove parentheses?\n",
- " \n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " assert (a == b, \"Values are not equal\")\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " Traceback (most recent call last):\n",
- " File \"\", line 1, in \n",
- " AssertionError: Values are not equal\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " assert a == b, \"Values are not equal\"\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "* 至于第五个片段,大多数修改序列/映射对象项的方法,如`list.append`、`dict.update`、`list.sort`等,都在原地修改对象并返回`None`。这背后的基本原理是通过原地操作,避免复制对象来提高性能(参考[这里](https://docs.python.org/3/faq/design.html#why-doesn-t-list-sort-return-the-sorted-list))。\n",
- "* 最后一个应该相当明显,可变对象(如`list`)可以在函数中更改,不可变对象(`a -= 1`)的重新赋值则不属于值的改变。\n",
- "* 了解这些细节可以在程序长期运行中,为您节省数小时的调试工作。\n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Splitsies/分割函数 *\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "['a']\n",
- "\n",
- "# is same as\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "'a'.split()\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "['a']\n",
- "\n",
- "# but\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "'a'.split(' ')\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "0\n",
- "\n",
- "# isn't the same as\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "len(''.split())\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "1\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "len(''.split(' '))\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明\n",
- "\n",
- "- 起初人们可能会认为 split 的默认分隔符是单个空格 `' '`,但根据 [文档](https://docs.python.org/3/library/stdtypes.html#str.split):\n",
- " > 如果 sep 未指定或为 `None`,则应用不同的拆分算法:连续的空格被视为单个分隔符,如果字符串有前导或尾随空格,则结果将在开头或结尾不包含空字符串。因此,使用 `None` 分隔符拆分空字符串或仅包含空格的字符串将返回 `[]`。\n",
- " > 如果给定 sep,连续的分隔符不会组合在一起,并被视为分隔空字符串(例如,`'1,,2'.split(',')` 返回 `['1', '', '2 ']`)。使用指定的分隔符拆分空字符串会返回 `['']`。\n",
- "- Noticing how the leading and trailing whitespaces are handled in the following snippet will make things clear,\n",
- "- 注意以下代码段中如何处理前导和尾随空格,促进更深入的理解:\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " ['', 'a', '']\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " ' a '.split(' ')\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " ['a']\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " ' a '.split()\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " ['']\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " ''.split(' ')\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > All sorted?/都排序了吗? *\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "False\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "x = 7, 8, 9\n",
- "sorted(x) == x\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True\n",
- "\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "sorted(x) == sorted(x)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "False\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "y = reversed(x)\n",
- "sorted(y) == sorted(y)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明\n",
- "\n",
- "- `sorted` 方法一定返回列表类型, 比较列表与元组在Python中一定返回 `False`. \n",
- "\n",
- "- ```py\n",
- " >>> [] == tuple()\n",
- " False\n",
- " >>> x = 7, 8, 9\n",
- " >>> type(x), type(sorted(x))\n",
- " (tuple, list)\n",
- " ```\n",
- "\n",
- "- 与 `sorted` 不同,`reversed` 方法返回一个迭代器。为什么?因为排序需要就地修改迭代器或使用额外的容器(列表),而反向可以简单地通过从最后一个索引迭代到第一个索引来工作。\n",
- "\n",
- "- 所以在比较 `sorted(y) == sorted(y)` 时,第一次调用 `sorted()` 会消耗迭代器 `y`,下一次调用只会返回一个空列表。\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " ([7, 8, 9], [])\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " x = 7, 8, 9\n",
- " y = reversed(x)\n",
- " sorted(y), sorted(y)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Midnight time doesn't exist?/不存在的午夜?\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "from datetime import datetime\n",
- "\n",
- "midnight = datetime(2018, 1, 1, 0, 0)\n",
- "midnight_time = midnight.time()\n",
- "\n",
- "noon = datetime(2018, 1, 1, 12, 0)\n",
- "noon_time = noon.time()\n",
- "\n",
- "if midnight_time:\n",
- " print(\"Time at midnight is\", midnight_time)\n",
- "\n",
- "if noon_time:\n",
- " print(\"Time at noon is\", noon_time)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n",
- "```sh\n",
- "('Time at noon is', datetime.time(12, 0))\n",
- "```\n",
- "\n",
- "midnight_time 并没有被输出.\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "\n",
- "在Python 3.5之前, 如果 `datetime.time` 对象存储的UTC的午夜时间(译: 就是 `00:00`), 那么它的布尔值会被认为是 `False`. 当使用 `if obj:` 语句来检查 `obj` 是否为 `null` 或者某些“空”值的时候, 很容易出错.\n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Okay Python, Can you make me fly?/Python, 可否带我飞? *\n",
- "好, 去吧.\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "import antigravity\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n",
- "嘘.. 这是个超级秘密.\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "+ `antigravity` 模块是 Python 开发人员发布的少数复活节彩蛋之一.\n",
- "+ `import antigravity` 会打开一个 Python 的[经典 XKCD 漫画](http://xkcd.com/353/)页面.\n",
- "+ 不止如此. 这个**复活节彩蛋里还有一个复活节彩蛋**. 如果你看一下[代码](https://github.com/python/cpython/blob/master/Lib/antigravity.py#L7-L17), 就会发现还有一个函数实现了 [XKCD's geohashing 算法](https://xkcd.com/426/).\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > `goto`, but why?/`goto`, 但为什么? *\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": []
- }
- ],
- "source": [
- "from goto import goto, label\n",
- "for i in range(9):\n",
- " for j in range(9):\n",
- " for k in range(9):\n",
- " print(\"I'm trapped, please rescue!\")\n",
- " if k == 2:\n",
- " goto .breakout # 从多重循环中跳出\n",
- "label .breakout\n",
- "print(\"Freedom!\")\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output (Python 2.3):**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "I'm trapped, please rescue!\n",
- "I'm trapped, please rescue!\n",
- "Freedom!\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "- 2004年4月1日, Python [宣布](https://mail.python.org/pipermail/python-announce-list/2004-April/002982.html) 加入一个可用的 `goto` 作为愚人节礼物.\n",
- "- 当前版本的 Python 并没有这个模块.\n",
- "- 就算可以用, 也请不要使用它. 这里是为什么Python中没有 `goto` 的[原因](https://docs.python.org/3/faq/design.html#why-is-there-no-goto).\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Brace yourself!/做好思想准备 *\n",
- "如果你不喜欢在Python中使用空格来表示作用域, 你可以导入 C 风格的 {},\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "from __future__ import braces\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " File \"some_file.py\", line 1\n",
- " from __future__ import braces\n",
- "SyntaxError: not a chance\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "想用大括号 `braces`? 没门! 觉得不爽, 请去用java。那么,另一个令人惊讶的事情,找一找在 `__future__` 模块中,哪里引发了 `SyntaxError` [code](https://github.com/python/cpython/blob/master/Lib/__future__.py)?\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "+ 通常 `__future__` 会提供 Python 未来版本的功能. 然而,这里的 “未来” 是一个讽刺.\n",
- "+ 这是一个表达社区对此类问题态度的复活节彩蛋.\n",
- "+ 代码实际上在[`future.c` 文件]中 (https://github.com/python/cpython/blob/025eb98dc0c1dc27404df6c544fc2944e0fa9f3a/Python/future.c#L49).\n",
- "+ 当 CPython 编译器遇到 [future表达式](https://docs.python.org/3.3/reference/simple_stmts.html#future-statements) 时,它首先在 `future.c` 中运行相应的代码,然后再对其进行处理作为正常的`import`表达式。\n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Let's meet Friendly Language Uncle For Life/让生活更友好 *\n",
- "**Output (Python 3.x)**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " File \"some_file.py\", line 1\n",
- " \"Ruby\" != \"Python\"\n",
- " ^\n",
- "SyntaxError: invalid syntax\n",
- "\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "from __future__ import barry_as_FLUFL\n",
- "\"Ruby\" != \"Python\" # 这里没什么疑问\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "\"Ruby\" <> \"Python\"\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "这就对了.\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "- 相关的 [PEP-401](https://www.python.org/dev/peps/pep-0401/) 发布于 2009年4月1日 (所以你现在知道这意味着什么了吧).\n",
- "- 引用 PEP-401\n",
- " > 意识到 Python 3.0 里的 != 运算符是一个会引起手指疼痛的恐怖错误, FLUFL 将 <> 运算符恢复为唯一写法.\n",
- "- Uncle Barry 在 PEP 中还分享了其他东西; 你可以在[这里](https://www.python.org/dev/peps/pep-0401/)获得他们.\n",
- "- (译: 虽然文档中没写,但应该是只能在交互解释器中使用.)\n",
- "- 它在交互式环境中正常运行,但是当您通过 python 文件运行时它会引发 `SyntaxError`(请参阅此 [问题](https://github.com/satwikkansal/wtfpython/issues/94))。您可以将表达式作为`eval` 或 `compile` 参数中使用。\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " from __future__ import barry_as_FLUFL\n",
- " print(eval('\"Ruby\" <> \"Python\"'))\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Even Python understands that love is complicated/连Python也知道爱是难言的 *\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "import this\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "等等, **this** 是什么? `this` 是爱 :heart:\n",
- "\n",
- "**Output:**\n",
- "```\n",
- "The Zen of Python, by Tim Peters\n",
- "\n",
- "Beautiful is better than ugly.\n",
- "优美胜于丑陋(Python 以编写优美的代码为目标)\n",
- "Explicit is better than implicit.\n",
- "明了胜于晦涩(优美的代码应当是明了的,命名规范,风格相似)\n",
- "Simple is better than complex.\n",
- "简洁胜于复杂(优美的代码应当是简洁的,不要有复杂的内部实现)\n",
- "Complex is better than complicated.\n",
- "复杂胜于凌乱(如果复杂不可避免,那代码间也不能有难懂的关系,要保持接口简洁)\n",
- "Flat is better than nested.\n",
- "扁平胜于嵌套(优美的代码应当是扁平的,不能有太多的嵌套)\n",
- "Sparse is better than dense.\n",
- "间隔胜于紧凑(优美的代码有适当的间隔,不要奢望一行代码解决问题)\n",
- "Readability counts.\n",
- "可读性很重要(优美的代码一定是可读的)\n",
- "Special cases aren't special enough to break the rules.\n",
- "没有特例特殊到需要违背这些规则(这些规则至高无上)\n",
- "Although practicality beats purity.\n",
- "尽管我们更倾向于实用性\n",
- "Errors should never pass silently.\n",
- "不要安静的包容所有错误\n",
- "Unless explicitly silenced.\n",
- "除非你确定需要这样做(精准地捕获异常,不写 except:pass 风格的代码)\n",
- "In the face of ambiguity, refuse the temptation to guess.\n",
- "拒绝诱惑你去猜测的暧昧事物\n",
- "There should be one-- and preferably only one --obvious way to do it.\n",
- "而是尽量找一种,最好是唯一一种明显的解决方案(如果不确定,就用穷举法)\n",
- "Although that way may not be obvious at first unless you're Dutch.\n",
- "虽然这并不容易,因为你不是 Python 之父(这里的 Dutch 是指 Guido )\n",
- "Now is better than never.\n",
- "现在行动好过永远不行动\n",
- "Although never is often better than *right* now.\n",
- "尽管不行动要好过鲁莽行动\n",
- "If the implementation is hard to explain, it's a bad idea.\n",
- "如果你无法向人描述你的方案,那肯定不是一个好方案;\n",
- "If the implementation is easy to explain, it may be a good idea.\n",
- "如果你能轻松向人描述你的方案,那也许会是一个好方案(方案测评标准)\n",
- "Namespaces are one honking great idea -- let's do more of those!\n",
- "命名空间是一种绝妙的理念,我们应当多加利用(倡导与号召)\n",
- "```\n",
- "\n",
- "这是 Python 之禅!\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "love = this\n",
- "this is love\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "False\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "love is True\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "False\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "love is False\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "love is not True or False\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "love is not True or False; love is love # 爱是难言的\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "\n",
- "* `this` 模块是关于 Python 之禅的复活节彩蛋 ([PEP 20](https://www.python.org/dev/peps/pep-0020)).\n",
- "* 如果你认为这已经够有趣的了, 可以看看 [this.py](https://hg.python.org/cpython/file/c3896275c0f6/Lib/this.py) 的实现. 有趣的是, Python 之禅的实现代码违反了他自己 (这可能是唯一会发生这种情况的地方).\n",
- "*\n",
- "至于 `love is not True or False; love is love`, 意外却又不言而喻.\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Yes, it exists!/是的, 它存在!\n",
- "**循环的 `else`.** 一个典型的例子:\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " def does_exists_num(l, to_find):\n",
- " for num in l:\n",
- " if num == to_find:\n",
- " print(\"Exists!\")\n",
- " break\n",
- " else:\n",
- " print(\"Does not exist\")\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "Exists!\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "some_list = [1, 2, 3, 4, 5]\n",
- "does_exists_num(some_list, 4)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "Does not exist\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "does_exists_num(some_list, -1)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**异常的 `else` .** 例,\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "try:\n",
- " pass\n",
- "except:\n",
- " print(\"Exception occurred!!!\")\n",
- "else:\n",
- " print(\"Try block executed successfully...\")\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "Try block executed successfully...\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "- 循环后的 `else` 子句只会在循环没有触发 `break` 语句, 正常结束的情况下才会执行.\n",
- "- try 之后的 `else` 子句也被称为 \"完成子句\", 因为在 `try` 语句中到达 `else` 子句意味着try块实际上已成功完成.\n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Ellipsis/省略 *\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "def some_func():\n",
- " Ellipsis\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "# 没有输出,也没有报错\n",
- "\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "some_func()\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "Traceback (most recent call last):\n",
- " File \"\", line 1, in \n",
- "NameError: name 'SomeRandomString' is not defined\n",
- "\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "SomeRandomString\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "Ellipsis\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "Ellipsis\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明\n",
- "- 在 Python 中,`Ellipsis` 是一个全局可用的内置对象,相当于`...`。\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " Ellipsis\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " ...\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "- 省略号可用于多种用途,\n",
- " + 作为尚未编写的代码的占位符(就像`pass`语句)\n",
- " + 在切片语法中表示完整切片的其余维度\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " array([\n",
- " [\n",
- " [0, 1],\n",
- " [2, 3]\n",
- " ],\n",
- "\n",
- " [\n",
- " [4, 5],\n",
- " [6, 7]\n",
- " ]\n",
- " ])\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " import numpy as np\n",
- " three_dimensional_array = np.arange(8).reshape(2, 2, 2)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- " 所以我们的 `three_dimensional_array` 是一个数组的数组的数组。假设我们要打印所有最内层数组的第二个元素(索引 `1`),我们可以使用 Ellipsis 绕过所有前面的维度\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " array([[1, 3],\n",
- " [5, 7]])\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " three_dimensional_array[:,:,1]\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " array([[1, 3],\n",
- " [5, 7]])\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " three_dimensional_array[..., 1] # 使用Ellipsis.\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- " 注意:这适用于任意数量的维度。您甚至可以在第一个和最后一个维度中选择切片并以这种方式忽略中间的切片(`n_dimensional_array[firs_dim_slice, ..., last_dim_slice]`)\n",
- "\n",
- " + 在 [类型提示](https://docs.python.org/3/library/typing.html)中仅表示类型的一部分(如 `(Callable[..., int]` 或 `Tuple[ str, ...]`))\n",
- "\n",
- " + 您也可以使用省略号作为默认函数参数(在您想要区分“无参数”和“传递None值”场景的情况下)。\n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Inpinity/无限 *\n",
- "英文拼写是有意的, 请不要为此提交补丁.\n",
- "(译: 这里是为了突出 Python 中无限的定义与[Pi](https://en.wikipedia.org/wiki/Pi)有关, 所以将两个单词拼接了.)\n",
- "\n",
- "**Output (Python 3.x):**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "314159\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "infinity = float('infinity')\n",
- "hash(infinity)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "-314159\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "hash(float('-inf'))\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "- infinity 的哈希值是 10⁵ x π.\n",
- "- 有意思的是, `float('-inf')` 的哈希值在 Python 3 中是 \"-10⁵ x π\" , 而在 Python 2 中是 \"-10⁵ x e\".\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Let's mangle/修饰时间! *\n",
- "1\\.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "class Yo(object):\n",
- " def __init__(self):\n",
- " self.__honey = True\n",
- " self.bro = True\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "Yo().bro\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "AttributeError: 'Yo' object has no attribute '__honey'\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "Yo().__honey\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "Yo()._Yo__honey\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "2\\.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "class Yo(object):\n",
- " def __init__(self):\n",
- " # 这次试试对称形式\n",
- " self.__honey__ = True\n",
- " self.bro = True\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True\n",
- "\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "Yo().bro\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "Traceback (most recent call last):\n",
- " File \"\", line 1, in \n",
- "AttributeError: 'Yo' object has no attribute '_Yo__honey__'\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "Yo()._Yo__honey__\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "为什么 `Yo()._Yo__honey` 能运行? 只有印度人理解.(译: 这个梗可能是指印度音乐人[Yo Yo Honey Singh](https://en.wikipedia.org/wiki/Yo_Yo_Honey_Singh))\n",
- "\n",
- "\n",
- "3\\.\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "_A__variable = \"Some value\"\n",
- "\n",
- "class A(object):\n",
- " def some_func(self):\n",
- " return __variable # 没在任何地方初始化\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "Traceback (most recent call last):\n",
- " File \"\", line 1, in \n",
- "AttributeError: 'A' object has no attribute '__variable'\n",
- "\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A().__variable\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "'Some value'\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A().some_func()\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "\n",
- "* [命名修饰](https://en.wikipedia.org/wiki/Name_mangling) 用于避免不同命名空间之间名称冲突.\n",
- "* 在 Python 中, 解释器会通过给类中以 `__` (双下划线)开头且结尾最多只有一个下划线的类成员名称加上`_NameOfTheClass` 来修饰(mangles)名称.\n",
- "* 所以, 要访问 `__honey` 对象,我们需要加上 `_Yo` 以防止与其他类中定义的相同名称的属性发生冲突.\n",
- "* 但是为什么它在第二个片段中不起作用? 因为命名修饰排除了以双下划线结尾的名称。\n",
- "* 第三个片段也是命名修饰的结果。 `return __variable` 语句中的 `__variable` 名称被修改为 `_A__variable`,这也恰好是我们在外部作用域中声明的变量的名称。\n",
- "* 此外,如果修饰后的变量名超过255个字符,则会进行截断。\n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Skipping lines?/跳过一行?\n",
- "**Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "11\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "value = 11\n",
- "valuе = 32\n",
- "value\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "什么鬼?\n",
- "\n",
- "**注意:** 如果你想要重现的话最简单的方法是直接复制上面的代码片段到你的文件或命令行里.\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "\n",
- "一些非西方字符虽然看起来和英语字母相同, 但会被解释器识别为不同的字母.\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "1077\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "ord('е') # 西里尔语的 'e' (Ye)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "101\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "ord('e') # 拉丁语的 'e', 用于英文并使用标准键盘输入\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "False\n",
- "\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "'е' == 'e'\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "42\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "value = 42 # 拉丁语 e\n",
- "valuе = 23 # 西里尔语 'e', Python 2.x 的解释器在这会抛出 `SyntaxError` 异常\n",
- "value\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "内置的 `ord()` 函数可以返回一个字符的 Unicode [代码点](https://en.wikipedia.org/wiki/Code_point), 这里西里尔语 'e' 和拉丁语 'e' 的代码点不同证实了上述例子.\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Teleportation/空间移动 *\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "import numpy as np\n",
- "\n",
- "def energy_send(x):\n",
- " # 初始化一个 numpy 数组\n",
- " np.array([float(x)])\n",
- "\n",
- "def energy_receive():\n",
- " # 返回一个空的 numpy 数组\n",
- " return np.empty((), dtype=np.float).tolist()\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "123.456\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "energy_send(123.456)\n",
- "energy_receive()\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "谁来给我发个诺贝尔奖?\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "\n",
- "* 注意在 `energy_send` 函数中创建的 numpy 数组并没有返回, 因此内存空间被释放并可以被重新分配.\n",
- "* `numpy.empty()` 直接返回下一段空闲内存,而不重新初始化. 而这个内存点恰好就是刚刚释放的那个(通常情况下, 并不绝对).\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Well, something is fishy.../嗯,有些可疑...\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "def square(x):\n",
- " \"\"\"\n",
- " 一个通过加法计算平方的简单函数.\n",
- " \"\"\"\n",
- " sum_so_far = 0\n",
- " for counter in range(x):\n",
- " sum_so_far = sum_so_far + x\n",
- " return sum_so_far\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output (Python 2.x):**\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "10\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "square(10)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "难道不应该是100吗?\n",
- "\n",
- "**注意:** 如果你无法重现, 可以尝试运行这个文件[mixed_tabs_and_spaces.py](/mixed_tabs_and_spaces.py).\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "\n",
- "* **不要混用制表符(tab)和空格(space)!** 在上面的例子中, return 的前面是\"1个制表符\", 而其他部分的代码前面是 \"4个空格\".\n",
- "* Python是这么处理制表符的:\n",
- " > 首先, 制表符会从左到右依次被替换成8个空格, 直到被替换后的字符总数是八的倍数 <...>\n",
- "* 因此, `square` 函数最后一行的制表符会被替换成8个空格, 导致return语句进入循环语句里面.\n",
- "* Python 3 很友好, 在这种情况下会自动抛出错误.\n",
- "\n",
- " **Output (Python 3.x):**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " TabError: inconsistent use of tabs and spaces in indentation\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > `+=` is faster/更快的 `+=`\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "0.25748300552368164\n",
- "# 用 \"+=\" 连接三个字符串:\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 用 \"+\" 连接三个字符串:\n",
- "timeit.timeit(\"s1 = s1 + s2 + s3\", setup=\"s1 = ' ' * 100000; s2 = ' ' * 100000; s3 = ' ' * 100000\", number=100)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "0.012188911437988281\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "timeit.timeit(\"s1 += s2 + s3\", setup=\"s1 = ' ' * 100000; s2 = ' ' * 100000; s3 = ' ' * 100000\", number=100)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "+ 连接两个以上的字符串时 `+=` 比 `+` 更快, 因为在计算过程中第一个字符串 (例如, `s1 += s2 + s3` 中的 `s1`) 不会被销毁.(译: 就是 `+=` 执行的是追加操作,少了一个销毁新建的动作.)\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Let's make a giant string!/来做个巨大的字符串吧!\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "def add_string_with_plus(iters):\n",
- " s = \"\"\n",
- " for i in range(iters):\n",
- " s += \"xyz\"\n",
- " assert len(s) == 3*iters\n",
- "\n",
- "def add_bytes_with_plus(iters):\n",
- " s = b\"\"\n",
- " for i in range(iters):\n",
- " s += b\"xyz\"\n",
- " assert len(s) == 3*iters\n",
- "\n",
- "def add_string_with_format(iters):\n",
- " fs = \"{}\"*iters\n",
- " s = fs.format(*([\"xyz\"]*iters))\n",
- " assert len(s) == 3*iters\n",
- "\n",
- "def add_string_with_join(iters):\n",
- " l = []\n",
- " for i in range(iters):\n",
- " l.append(\"xyz\")\n",
- " s = \"\".join(l)\n",
- " assert len(s) == 3*iters\n",
- "\n",
- "def convert_list_to_string(l, iters):\n",
- " s = \"\".join(l)\n",
- " assert len(s) == 3*iters\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "1000 loops, best of 3: 972 µs per loop\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "timeit(add_string_with_plus(10000))\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "1000 loops, best of 3: 815 µs per loop\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "timeit(add_bytes_with_plus(10000))\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "1000 loops, best of 3: 508 µs per loop\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "timeit(add_string_with_format(10000))\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "1000 loops, best of 3: 878 µs per loop\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "timeit(add_string_with_join(10000))\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "10000 loops, best of 3: 80 µs per loop\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "l = [\"xyz\"]*10000\n",
- "timeit(convert_list_to_string(l, 10000))\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "让我们将迭代次数增加10倍.\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "100 loops, best of 3: 9.75 ms per loop\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "timeit(add_string_with_plus(100000)) # 执行时间线性增加\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "1000 loops, best of 3: 974 ms per loop\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "timeit(add_bytes_with_plus(100000)) # 二次增加\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "100 loops, best of 3: 5.25 ms per loop\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "timeit(add_string_with_format(100000)) # 线性增加\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "100 loops, best of 3: 9.85 ms per loop\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "timeit(add_string_with_join(100000)) # 线性增加\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "1000 loops, best of 3: 723 µs per loop\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "l = [\"xyz\"]*100000\n",
- "timeit(convert_list_to_string(l, 100000)) # 线性增加\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明:\n",
- "- 你可以在这获得更多 [timeit](https://docs.python.org/3/library/timeit.html) 的相关信息. 它通常用于衡量代码片段的执行时间.\n",
- "- 不要用 `+` 去生成过长的字符串, 在 Python 中, `str` 是不可变的, 所以在每次连接中你都要把左右两个字符串复制到新的字符串中. 如果你连接四个长度为10的字符串, 你需要拷贝 (10+10) + ((10+10)+10) + (((10+10)+10)+10) = 90 个字符而不是 40 个字符. 随着字符串的数量和大小的增加, 情况会变得越发的糟糕 (就像`add_bytes_with_plus` 函数的执行时间一样)\n",
- "- 因此, 更建议使用 `.format.` 或 `%` 语法 (但是, 对于短字符串, 它们比 `+` 稍慢一点).\n",
- "- 又或者, 如果你所需的内容已经以可迭代对象的形式提供了, 使用 `''.join(可迭代对象)` 要快多了.\n",
- "- `add_string_with_plus` 的执行时间没有像 `add_bytes_with_plus` 一样出现二次增加是因为解释器会如同上一个例子所讨论的一样优化 `+=`. 用 `s = s + \"x\" + \"y\" + \"z\"` 替代 `s += \"xyz\"` 的话, 执行时间就会二次增加了.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " 100 loops, best of 3: 9.87 ms per loop\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " def add_string_with_plus(iters):\n",
- " s = \"\"\n",
- " for i in range(iters):\n",
- " s = s + \"x\" + \"y\" + \"z\"\n",
- " assert len(s) == 3*iters\n",
- "\n",
- " timeit(add_string_with_plus(10000))\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- " 1 loops, best of 3: 1.09 s per loop\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- " timeit(add_string_with_plus(100000)) # 执行时间二次增加\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Slowing down `dict` lookups/让字典的查找慢下来 *\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "some_dict = {str(i): 1 for i in range(1_000_000)}\n",
- "another_dict = {str(i): 1 for i in range(1_000_000)}\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:**\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "28.6 ns ± 0.115 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "%timeit some_dict['5']\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "37.2 ns ± 0.265 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)\n",
- "\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "some_dict[1] = 1\n",
- "%timeit some_dict['5']\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "28.5 ns ± 0.142 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "%timeit another_dict['5']\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "Traceback (most recent call last):\n",
- " File \"\", line 1, in \n",
- "KeyError: 1\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "another_dict[1] # Trying to access a key that doesn't exist\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "38.5 ns ± 0.0913 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "%timeit another_dict['5']\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "为什么相同的查找会变得越来越慢?\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明\n",
- "+ CPython 有一个通用的字典查找函数,可以处理所有类型的键(`str`、`int`、任何对象...),以及一个专门用于处理仅由 `str` 键组成的字典的常见情况。\n",
- "+ 专用函数(在 CPython 的 [源](https://github.com/python/cpython/blob/522691c46e2ae51faaad5bbbce7d959dd61770df/Objects/dictobject.c#L841) 中名为 `lookdict_unicode`)知道所有现有的键(包括查找的 key) 是字符串,并使用更快和更简单的字符串比较来比较键,而不是调用 `__eq__` 方法。\n",
- "+ 第一次使用非 `str` 键访问 `dict` 实例时,会对其进行修改,以便将来的查找使用通用函数。\n",
- "+ 这个过程对于特定的 `dict` 实例是不可逆的,并且键甚至不必存在于字典中。 这就是为什么对不存在的键进行查找具有相同副作用的原因。\n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Bloating instance `dict`s/变臃肿的`dict`实例们 *\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "import sys\n",
- "\n",
- "class SomeClass:\n",
- " def __init__(self):\n",
- " self.some_attr1 = 1\n",
- " self.some_attr2 = 2\n",
- " self.some_attr3 = 3\n",
- " self.some_attr4 = 4\n",
- "\n",
- "\n",
- "def dict_size(o):\n",
- " return sys.getsizeof(o.__dict__)\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output:** (Python 3.8, 其他 Python 3 的版本也许稍有不同)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "104\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "o1 = SomeClass()\n",
- "o2 = SomeClass()\n",
- "dict_size(o1)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "104\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "dict_size(o2)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "232\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "del o1.some_attr1\n",
- "o3 = SomeClass()\n",
- "dict_size(o3)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "232\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "dict_size(o1)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "让我们在一个新的解释器中再试一次:\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "104 # 意料之中\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "o1 = SomeClass()\n",
- "o2 = SomeClass()\n",
- "dict_size(o1)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "360\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "o1.some_attr5 = 5\n",
- "o1.some_attr6 = 6\n",
- "dict_size(o1)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "272\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "dict_size(o2)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "232\n"
- ]
- },
- "execution_count": null,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "o3 = SomeClass()\n",
- "dict_size(o3)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "是什么让那些字典变得臃肿? 为什么新创建的对象也会变臃肿?\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明\n",
- "+ CPython 能够在多个字典中重用相同的“键”对象。 这添加在 [PEP 412](https://www.python.org/dev/peps/pep-0412/) 中,目的是减少内存使用,特别是在实例字典中 —— 键(实例属性)几乎在所有实例都通用。\n",
- "+ 这种优化对于实例字典来说是十分自然的,但如果某些假设被打破,它就会被禁用。\n",
- "+ 密钥共享字典不支持删除;如果删除了实例属性,则字典是“未共享的”,并且同一类的所有未来实例都禁用密钥共享。\n",
- "+ 另外,如果字典键已被调整大小(因为插入了新键),它们保持共享*仅当*它们被一个完全单一的字典使用时(这允许在第一个创建的实例的 `__init__` 中添加许多属性,而不会导致“取消共享”)。如果发生调整大小时存在多个实例,则为同一类的所有未来实例禁用密钥共享:CPython 无法判断您的实例是否正在使用相同的属性集,并决定放弃尝试共享它们的键值。\n",
- "+ 一个小提示,如果你的目标是降低程序的内存占用:不要删除实例属性,并确保在 `__init__` 中初始化所有的属性!\n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Minor Ones/小知识点\n",
- "* `join()` 是一个字符串操作而不是列表操作. (第一次接触会觉得有点违反直觉)\n",
- "\n",
- " **💡 说明:**\n",
- " 如果 `join()` 是字符串方法 那么它就可以处理任何可迭代的对象(列表,元组,迭代器). 如果它是列表方法, 则必须在每种类型中单独实现. 另外, 在 `list` 对象的通用API中实现一个专用于字符串的方法没有太大的意义.\n",
- "\n",
- "* 看着奇怪但能正确运行的语句:\n",
- " + `[] = ()` 语句在语义上是正确的 (解包一个空的 `tuple` 并赋值给 `list`)\n",
- " + `'a'[0][0][0][0][0]` 在语义上也是正确的, 因为在 Python 中字符串同时也是[序列](https://docs.python.org/3/glossary.html#term-sequence)(可迭代对象支持使用整数索引访问元素).\n",
- " + `3 --0-- 5 == 8` 和 `--5 == 5` 在语义上都是正确的, 且结果等于 `True`.(译: 3减负0等于3,再减负5相当于加5等于8;负的负5等于5.)\n",
- "\n",
- "* 鉴于 `a` 是一个数字, `++a` 和 `--a` 都是有效的 Python 语句, 但其效果与 C, C++ 或 Java 等不一样.\n",
- " ```py\n",
- " >>> a = 5\n",
- " >>> a\n",
- " 5\n",
- " >>> ++a\n",
- " 5\n",
- " >>> --a\n",
- " 5\n",
- " ```\n",
- "\n",
- " **💡 说明:**\n",
- " + python 里没有 `++` 操作符. 这其实是两个 `+` 操作符.\n",
- " + `++a` 被解析为 `+(+a)` 最后等于 `a`. `--a` 同理.\n",
- " + 这个 StackOverflow [回答](https://stackoverflow.com/questions/3654830/why-are-there-no-and-operators-in-python) 讨论了为什么 Python 中缺少增量和减量运算符.\n",
- "\n",
- "* Python 使用 2个字节存储函数中的本地变量. 理论上, 这意味着函数中只能定义65536个变量. 但是,Python 内置了一个方便的解决方案,可用于存储超过2^16个变量名. 下面的代码演示了当定义了超过65536个局部变量时堆栈中发生的情况 (警告: 这段代码会打印大约2^18行文本, 请做好准备!):\n",
- " ```py\n",
- " import dis\n",
- " exec(\"\"\"\n",
- " def f():\n",
- " \"\"\" + \"\"\"\n",
- " \"\"\".join([\"X\"+str(x)+\"=\" + str(x) for x in range(65539)]))\n",
- "\n",
- " f()\n",
- "\n",
- " print(dis.dis(f))\n",
- " ```\n",
- "\n",
- "* 你的 *Python 代码* 并不会多线程同时运行 (是的, 你没听错!). 虽然你觉得会产生多个线程并让它们同时执行你的代码, 但是, 由于 [全局解释锁](https://wiki.python.org/moin/GlobalInterpreterLock)的存在, 你所做的只是让你的线程依次在同一个核心上执行. Python 多线程适用于IO密集型的任务, 但如果想要并行处理CPU密集型的任务, 你应该会想使用 [multiprocessing](https://docs.python.org/2/library/multiprocessing.html) 模块.\n",
- "\n",
- "* 列表切片超出索引边界而不引发任何错误\n",
- " ```py\n",
- " >>> some_list = [1, 2, 3, 4, 5]\n",
- " >>> some_list[111:]\n",
- " []\n",
- " ```\n",
- "\n",
- "* `int('١٢٣٤٥٦٧٨٩')` 在 Python 3 中会返回 `123456789`. 在 Python 中, 十进制字符包括数字字符, 以及可用于形成十进制数字的所有字符, 例如: U+0660, ARABIC-INDIC DIGIT ZERO. 这有一个关于此的 [有趣故事](http://chris.improbable.org/2014/8/25/adventures-in-unicode-digits/).\n",
- "\n",
- "* `'abc'.count('') == 4`. 这有一个 `count` 方法的相近实现, 能更好的说明问题\n",
- " ```py\n",
- " def count(s, sub):\n",
- " result = 0\n",
- " for i in range(len(s) + 1 - len(sub)):\n",
- " result += (s[i:i + len(sub)] == sub)\n",
- " return result\n",
- " ```\n",
- " 这个行为是由于空子串(`''`)与原始字符串中长度为0的切片相匹配导致的.\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > First things first!/要事优先 *\n",
- "众所周知,Python 3.8 推出\"海象\"运算符 (`:=`) 方便易用,让我们一起看看。\n",
- "\n",
- "1\\.\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "```py\n",
- "# Python 版本 3.8+\n",
- "\n",
- ">>> a = \"wtf_walrus\"\n",
- ">>> a\n",
- "```\n",
- "```py\n",
- "'wtf_walrus'\n",
- "\n",
- "```\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "```py\n",
- ">>> a := \"wtf_walrus\"\n",
- "```\n",
- "```py\n",
- "File \"\", line 1\n",
- " a := \"wtf_walrus\"\n",
- " ^\n",
- "SyntaxError: invalid syntax\n",
- "\n",
- "```\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "```py\n",
- ">>> (a := \"wtf_walrus\") # 该语句有效\n",
- "```\n",
- "```py\n",
- "'wtf_walrus'\n",
- "```\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "```py\n",
- ">>> a\n",
- "```\n",
- "```py\n",
- "'wtf_walrus'\n",
- "```\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "2 \\.\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "```py\n",
- "# Python 版本 3.8+\n",
- "\n",
- ">>> a = 6, 9\n",
- ">>> a\n",
- "```\n",
- "```py\n",
- "(6, 9)\n",
- "\n",
- "```\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "```py\n",
- ">>> (a := 6, 9)\n",
- "```\n",
- "```py\n",
- "(6, 9)\n",
- "```\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "```py\n",
- ">>> a\n",
- "```\n",
- "```py\n",
- "6\n",
- "\n",
- "```\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "```py\n",
- ">>> a, b = 6, 9 # 典型拆包操作\n",
- ">>> a, b\n",
- "```\n",
- "```py\n",
- "(6, 9)\n",
- "```\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "```py\n",
- ">>> (a, b = 16, 19) # 出错啦\n",
- "```\n",
- "```py\n",
- " File \"\", line 1\n",
- " (a, b = 16, 19)\n",
- " ^\n",
- "SyntaxError: invalid syntax\n",
- "\n",
- "```\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "```py\n",
- ">>> (a, b := 16, 19) # 这里的结果是一个奇怪的三元组\n",
- "```\n",
- "```py\n",
- "(6, 16, 19)\n",
- "\n",
- "```\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "```py\n",
- ">>> a # a值仍然没变?\n",
- "```\n",
- "```py\n",
- "6\n",
- "\n",
- "```\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "```py\n",
- ">>> b\n",
- "```\n",
- "```py\n",
- "16\n",
- "```\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明\n",
- "\n",
- "**“海象”运算符简介**\n",
- "\n",
- "海象运算符 (`:=`) 在Python 3.8中被引入,用来在表达式中为变量赋值。\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "```py\n",
- "def some_func():\n",
- " # 假设这儿有一些耗时的计算\n",
- " # time.sleep(1000)\n",
- " return 5\n",
- "\n",
- "# 引入“海象”运算符前的例子\n",
- "if some_func():\n",
- " print(some_func()) # 糟糕的案例——函数运算了两次\n",
- "\n",
- "# 或者,加以改进:\n",
- "a = some_func()\n",
- "if a:\n",
- " print(a)\n",
- "\n",
- "# 有了“海象”运算符,你可以写的更简洁:\n",
- "if a := some_func():\n",
- " print(a)\n",
- "```\n",
- "```py\n",
- "```\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**输出 (> Python 3.8):**\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "```py\n",
- "5\n",
- "5\n",
- "5\n",
- "```\n",
- "```py\n",
- "```\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "这样既减少了一行代码,又避免了两次调用 `some_func` 函数。\n",
- "\n",
- "- 在顶层的无括号赋值操作(使用“海象”运算符)被限制,因此例1中的 `a := \"wtf_walrus\"` 出现了 `SyntaxError` 。用括号括起来。它就能正常工作了。\n",
- "\n",
- "- 一般的,包含 `=` 操作的表达式是不能用括号括起来的,因此 `(a, b = 6, 9)` 中出现了语法错误。\n",
- "\n",
- "- “海象”运算符的语法形式为:`NAME:= expr`,`NAME` 是一个有效的标识符,而 `expr` 是一个有效的表达式。 因此,这意味着它不支持可迭代的打包和拆包。\n",
- "\n",
- " - `(a := 6, 9)` 等价于 `((a := 6), 9)` ,最终得到 `(a, 9) ` (其中 `a` 的值为6)\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "```py\n",
- " >>> (a := 6, 9) == ((a := 6), 9)\n",
- "```\n",
- "```py\n",
- " True\n",
- "```\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "```py\n",
- " >>> x = (a := 696, 9)\n",
- " >>> x\n",
- "```\n",
- "```py\n",
- " (696, 9)\n",
- "```\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "```py\n",
- " >>> x[0] is a # 两个变量指向同一内存空间\n",
- "```\n",
- "```py\n",
- " True\n",
- "```\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- " - 类似的, `(a, b := 16, 19)` 等价于 `(a, (b := 16), 19)` ,只是一个三元组。 \n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### > Wild imports/通配符导入方式 *\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "```py\n",
- "# File: module.py\n",
- "\n",
- "def some_weird_name_func_():\n",
- " print(\"works!\")\n",
- "\n",
- "def _another_weird_name_func():\n",
- " print(\"works!\")\n",
- "\n",
- "```\n",
- "```py\n",
- "```\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "**Output**\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "```py\n",
- ">>> from module import *\n",
- ">>> some_weird_name_func_()\n",
- "```\n",
- "```py\n",
- "\"works!\"\n",
- "```\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "```py\n",
- ">>> _another_weird_name_func()\n",
- "```\n",
- "```py\n",
- "Traceback (most recent call last):\n",
- " File \"\", line 1, in \n",
- "NameError: name '_another_weird_name_func' is not defined\n",
- "```\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 💡 说明\n",
- "\n",
- "- 通常建议不要使用通配符导入。第一个明显的原因是,在通配符导入中,带有前导下划线的名称不会被导入。这可能会导致运行时出错。\n",
- "- 如果我们使用 `from ... import a, b, c` 语法,上面的 `NameError` 就不会发生。\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "```py\n",
- " >>> from module import some_weird_name_func_, _another_weird_name_func\n",
- " >>> _another_weird_name_func()\n",
- "```\n",
- "```py\n",
- " works!\n",
- "```\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "- 如果你真的想使用通配符导入,那么你必须在你的模块中定义列表`__all__`,它包含一系列公共对象,当我们进行通配符导入时,列表中的这些对象将被导入。\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "```py\n",
- " __all__ = ['_another_weird_name_func']\n",
- "\n",
- " def some_weird_name_func_():\n",
- " print(\"works!\")\n",
- "\n",
- " def _another_weird_name_func():\n",
- " print(\"works!\")\n",
- "```\n",
- "```py\n",
- "```\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- " **Output**\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "```py\n",
- " >>> _another_weird_name_func()\n",
- "```\n",
- "```py\n",
- " \"works!\"\n",
- "```\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "```py\n",
- " >>> some_weird_name_func_()\n",
- "```\n",
- "```py\n",
- " Traceback (most recent call last):\n",
- " File \"\", line 1, in \n",
- " NameError: name 'some_weird_name_func_' is not defined\n",
- "```\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Contributing/贡献\n",
- "\n",
- "欢迎各种补丁! 详情请看[CONTRIBUTING.md](https://github.com/satwikkansal/wtfpython/blob/master/CONTRIBUTING.md).(译: 这是给原库提贡献的要求模版)\n",
- "\n",
- "你可以通过新建 [issue](https://github.com/satwikkansal/wtfpython/issues/new) 或者在上 [Gitter](https://gitter.im/wtfpython/Lobby) 与我们进行讨论.\n",
- "\n",
- "(译: 如果你想对这个翻译项目提供帮助, 请看[这里](https://github.com/leisurelicht/wtfpython-cn/blob/master/CONTRIBUTING.md))\n",
- "\n",
- "# Acknowledgements/致谢\n",
- "\n",
- "这个系列最初的想法和设计灵感来自于 Denys Dovhan 的项目 [wtfjs](https://github.com/denysdovhan/wtfjs). 社区的强大支持让它成长为现在的模样.\n",
- "\n",
- "#### Some nice Links!/一些不错的资源\n",
- "* https://www.youtube.com/watch?v=sH4XF6pKKmk\n",
- "* https://www.reddit.com/r/Python/comments/3cu6ej/what_are_some_wtf_things_about_python\n",
- "* https://sopython.com/wiki/Common_Gotchas_In_Python\n",
- "* https://stackoverflow.com/questions/530530/python-2-x-gotchas-and-landmines\n",
- "* https://stackoverflow.com/questions/1011431/common-pitfalls-in-python\n",
- "* https://www.python.org/doc/humor/\n",
- "* https://www.codementor.io/satwikkansal/python-practices-for-efficient-code-performance-memory-and-usability-aze6oiq65\n",
- "\n",
- "# 🎓 License/许可\n",
- "\n",
- "[![CC 4.0][license-image]][license-url]\n",
- "\n",
- "© [Satwik Kansal](https://satwikkansal.xyz)\n",
- "\n",
- "[license-url]: http://www.wtfpl.net\n",
- "[license-image]: https://img.shields.io/badge/License-WTFPL%202.0-lightgrey.svg?style=flat-square\n",
- "\n"
- ]
- }
- ],
- "metadata": {
- "language_info": {
- "name": "python"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "What the f*ck Python! \ud83d\udc0d
\n",
+ "\u4e00\u4e9b\u6709\u8da3\u4e14\u9c9c\u4e3a\u4eba\u77e5\u7684 Python \u7279\u6027.
\n",
+ "\n",
+ "\u7ffb\u8bd1\u7248\u672c: [English](https://github.com/satwikkansal/wtfpython) | [Vietnamese Ti\u1ebfng Vi\u1ec7t](https://github.com/vuduclyunitn/wtfptyhon-vi) | [Spanish Espa\u00f1ol](https://web.archive.org/web/20220511161045/https://github.com/JoseDeFreitas/wtfpython-es) | [Korean \ud55c\uad6d\uc5b4](https://github.com/buttercrab/wtfpython-ko) | [Russian \u0420\u0443\u0441\u0441\u043a\u0438\u0439](https://github.com/frontdevops/wtfpython) | [Add translation](https://github.com/satwikkansal/wtfpython/issues/new?title=Add%20translation%20for%20[LANGUAGE]&body=Expected%20time%20to%20finish:%20[X]%20weeks.%20I%27ll%20start%20working%20on%20it%20from%20[Y].)\n",
+ "\n",
+ "\n",
+ "\u5176\u4ed6\u6a21\u5f0f: [Interactive](https://mybinder.org/v2/gh/robertparley/wtfpython-cn/master?labpath=irrelevant%2Fwtf.ipynb) \n",
+ "\n",
+ "\n",
+ "[![WTFPL 2.0][license-image]][license-url] [![Commit id][commit-image]][commit-url] [![996.icu][996.icu-image]][996.icu-url]\n",
+ "\n",
+ "\n",
+ "Python, \u662f\u4e00\u4e2a\u8bbe\u8ba1\u4f18\u7f8e\u7684\u89e3\u91ca\u578b\u9ad8\u7ea7\u8bed\u8a00, \u5b83\u63d0\u4f9b\u4e86\u5f88\u591a\u80fd\u8ba9\u7a0b\u5e8f\u5458\u611f\u5230\u8212\u9002\u7684\u529f\u80fd\u7279\u6027. \u4f46\u6709\u7684\u65f6\u5019, Python \u7684\u4e00\u4e9b\u8f93\u51fa\u7ed3\u679c\u5bf9\u4e8e\u521d\u5b66\u8005\u6765\u8bf4\u4f3c\u4e4e\u5e76\u4e0d\u662f\u90a3\u4e48\u4e00\u76ee\u4e86\u7136.\n",
+ "\n",
+ "\u8fd9\u4e2a\u6709\u8da3\u7684\u9879\u76ee\u610f\u5728\u6536\u96c6 Python \u4e2d\u90a3\u4e9b\u96be\u4ee5\u7406\u89e3\u548c\u53cd\u4eba\u7c7b\u76f4\u89c9\u7684\u4f8b\u5b50\u4ee5\u53ca\u9c9c\u4e3a\u4eba\u77e5\u7684\u529f\u80fd\u7279\u6027, \u5e76\u5c1d\u8bd5\u8ba8\u8bba\u8fd9\u4e9b\u73b0\u8c61\u80cc\u540e\u771f\u6b63\u7684\u539f\u7406!\n",
+ "\n",
+ "\u867d\u7136\u4e0b\u9762\u7684\u6709\u4e9b\u4f8b\u5b50\u5e76\u4e0d\u4e00\u5b9a\u4f1a\u8ba9\u4f60\u89c9\u5f97 WTFs, \u4f46\u5b83\u4eec\u4f9d\u7136\u6709\u53ef\u80fd\u4f1a\u544a\u8bc9\u4f60\u4e00\u4e9b\u4f60\u6240\u4e0d\u77e5\u9053\u7684 Python \u6709\u8da3\u7279\u6027. \u6211\u89c9\u5f97\u8fd9\u662f\u4e00\u79cd\u5b66\u4e60\u7f16\u7a0b\u8bed\u8a00\u5185\u90e8\u539f\u7406\u7684\u597d\u529e\u6cd5, \u800c\u4e14\u6211\u76f8\u4fe1\u4f60\u4e5f\u4f1a\u4ece\u4e2d\u83b7\u5f97\u4e50\u8da3!\n",
+ "\n",
+ "\u5982\u679c\u60a8\u662f\u4e00\u4f4d\u7ecf\u9a8c\u6bd4\u8f83\u4e30\u5bcc\u7684 Python \u7a0b\u5e8f\u5458, \u4f60\u53ef\u4ee5\u5c1d\u8bd5\u6311\u6218\u770b\u662f\u5426\u80fd\u4e00\u6b21\u5c31\u627e\u5230\u4f8b\u5b50\u7684\u6b63\u786e\u7b54\u6848. \u4f60\u53ef\u80fd\u5bf9\u5176\u4e2d\u7684\u4e00\u4e9b\u4f8b\u5b50\u5df2\u7ecf\u6bd4\u8f83\u719f\u6089\u4e86, \u90a3\u8fd9\u4e5f\u8bb8\u80fd\u5524\u8d77\u4f60\u5f53\u5e74\u8e29\u8fd9\u4e9b\u5751\u65f6\u7684\u751c\u871c\u56de\u5fc6 :sweat_smile:\n",
+ "\n",
+ "PS: \u5982\u679c\u4f60\u4e0d\u662f\u7b2c\u4e00\u6b21\u8bfb\u4e86, \u4f60\u53ef\u4ee5\u5728[\u8fd9\u91cc](https://github.com/satwikkansal/wtfpython/releases/)\u83b7\u53d6\u53d8\u52a8\u5185\u5bb9.\n",
+ "\n",
+ "\u90a3\u4e48, \u8ba9\u6211\u4eec\u5f00\u59cb\u5427...\n",
+ "\n",
+ "# Table of Contents/\u76ee\u5f55\n",
+ "\n",
+ "\n",
+ "- [Table of Contents/\u76ee\u5f55](#table-of-contents\u76ee\u5f55)\n",
+ "- [Structure of the Examples/\u793a\u4f8b\u7ed3\u6784](#structure-of-the-examples\u793a\u4f8b\u7ed3\u6784)\n",
+ "- [Usage/\u7528\u6cd5](#usage\u7528\u6cd5)\n",
+ "- [\ud83d\udc40 Examples/\u793a\u4f8b](#-examples\u793a\u4f8b)\n",
+ " - [Section: Strain your brain!/\u5927\u8111\u8fd0\u52a8!](#section-strain-your-brain\u5927\u8111\u8fd0\u52a8)\n",
+ " - [> First things first!/\u8981\u4e8b\u4f18\u5148 *](#-First-things-first!/\u8981\u4e8b\u4f18\u5148-*)\n",
+ " - [> Strings can be tricky sometimes/\u5fae\u5999\u7684\u5b57\u7b26\u4e32 *](#-strings-can-be-tricky-sometimes\u5fae\u5999\u7684\u5b57\u7b26\u4e32-)\n",
+ " - [> Be careful with chained operations/\u5c0f\u5fc3\u94fe\u5f0f\u64cd\u4f5c](#-be-careful-with-chained-operations\u5c0f\u5fc3\u94fe\u5f0f\u64cd\u4f5c)\n",
+ " - [> How not to use `is` operator/\u4e3a\u4ec0\u4e48\u4e0d\u4f7f\u7528 `is` \u64cd\u4f5c\u7b26](#-How-not-to-use-is-operator/\u4e3a\u4ec0\u4e48\u4e0d\u4f7f\u7528-is-\u64cd\u4f5c\u7b26-)\n",
+ " - [> Hash brownies/\u662f\u65f6\u5019\u6765\u70b9\u86cb\u7cd5\u4e86!](#-Hash-brownies\u662f\u65f6\u5019\u6765\u70b9\u86cb\u7cd5\u4e86)\n",
+ " - [> Deep down, we're all the same./\u672c\u8d28\u4e0a,\u6211\u4eec\u90fd\u4e00\u6837. *](#-deep-down-were-all-the-same\u672c\u8d28\u4e0a\u6211\u4eec\u90fd\u4e00\u6837-)\n",
+ " - [> Disorder within order/\u6709\u5e8f\u4e2d\u6f5c\u85cf\u7740\u65e0\u5e8f *](#-disorder-within-order/\u6709\u5e8f\u4e2d\u6f5c\u85cf\u7740\u65e0\u5e8f-*)\n",
+ " - [> Keep trying.../\u4e0d\u505c\u7684try *](#-Keep-trying\u4e0d\u505c\u7684try-)\n",
+ " - [> For what?/\u4e3a\u4ec0\u4e48?](#-for-what\u4e3a\u4ec0\u4e48)\n",
+ " - [> Evaluation time discrepancy/\u6267\u884c\u65f6\u673a\u5dee\u5f02](#-evaluation-time-discrepancy\u6267\u884c\u65f6\u673a\u5dee\u5f02)\n",
+ " - [> `is not ...` is not `is (not ...)` / `is not ...` \u4e0d\u662f `is (not ...)`](#-is-not--is-not-is-not-is-not--\u4e0d\u662f-is-not-)\n",
+ " - [> A tic-tac-toe where X wins in the first attempt!/\u4e00\u8e74\u5373\u81f3!](#-a-tic-tac-toe-where-x-wins-in-the-first-attempt\u4e00\u8e74\u5373\u81f3)\n",
+ " - [> Schr\u00f6dinger's variable/\u859b\u5b9a\u8c14\u7684\u53d8\u91cf *](#-Schr\u00f6dingers-variable\u859b\u5b9a\u8c14\u7684\u53d8\u91cf-)\n",
+ " - [> The chicken-egg problem/\u5148\u6709\u9e21\u8fd8\u662f\u5148\u6709\u86cb *](#-the-chicken-egg-problem/\u5148\u6709\u9e21\u8fd8\u662f\u5148\u6709\u86cb-*)\n",
+ " - [> Subclass relationships/\u5b50\u7c7b\u5173\u7cfb *](#-subclass-relationships\u5b50\u7c7b\u5173\u7cfb-)\n",
+ " - [> Methods equality and identity/\u65b9\u6cd5\u7684\u76f8\u7b49\u6027\u548c\u552f\u4e00\u6027 *](#-Methods-equality-and-identity/\u65b9\u6cd5\u7684\u76f8\u7b49\u6027\u548c\u552f\u4e00\u6027-)\n",
+ " - [> All-true-ation/\u8fd4\u56deTrue\u7684all\u51fd\u6570 *](#-All-true-ation/\u8fd4\u56deTrue\u7684all\u51fd\u6570-)\n",
+ " - [> The surprising comma/\u610f\u5916\u7684\u9017\u53f7](#-the-surprising-comma\u610f\u5916\u7684\u9017\u53f7)\n",
+ " - [> Strings and the backslashes/\u5b57\u7b26\u4e32\u4e0e\u53cd\u659c\u6760](#-strings-and-the-backslashes\u5b57\u7b26\u4e32\u4e0e\u53cd\u659c\u6760)\n",
+ " - [> not knot!/\u522b\u7ea0\u7ed3!](#-not-knot\u522b\u7ea0\u7ed3)\n",
+ " - [> Half triple-quoted strings/\u4e09\u4e2a\u5f15\u53f7](#-half-triple-quoted-strings\u4e09\u4e2a\u5f15\u53f7)\n",
+ " - [> What's wrong with booleans?/\u5e03\u5c14\u4f60\u548b\u4e86?](#-whats-wrong-with-booleans\u5e03\u5c14\u4f60\u548b\u4e86)\n",
+ " - [> Class attributes and instance attributes/\u7c7b\u5c5e\u6027\u548c\u5b9e\u4f8b\u5c5e\u6027](#-class-attributes-and-instance-attributes\u7c7b\u5c5e\u6027\u548c\u5b9e\u4f8b\u5c5e\u6027)\n",
+ " - [> yielding None/\u751f\u6210 None](#-yielding-none\u751f\u6210-none)\n",
+ " - [> Yielding from... return!/\u751f\u6210\u5668\u91cc\u7684return *](#-Yielding-from-return/\u751f\u6210\u5668\u91cc\u7684return-)\n",
+ " - [> Nan-reflexivity/Nan\u7684\u81ea\u53cd\u6027](#-Nan-reflexivityNan\u7684\u81ea\u53cd\u6027)\n",
+ " - [> Mutating the immutable!/\u5f3a\u4eba\u6240\u96be](#-mutating-the-immutable\u5f3a\u4eba\u6240\u96be)\n",
+ " - [> The disappearing variable from outer scope/\u6d88\u5931\u7684\u5916\u90e8\u53d8\u91cf](#-the-disappearing-variable-from-outer-scope\u6d88\u5931\u7684\u5916\u90e8\u53d8\u91cf)\n",
+ " - [> The mysterious key type conversion/\u795e\u79d8\u7684\u952e\u578b\u8f6c\u6362 *](#-the-mysterious-key-type-conversion\u795e\u79d8\u7684\u952e\u578b\u8f6c\u6362-)\n",
+ " - [> Let's see if you can guess this?/\u770b\u770b\u4f60\u80fd\u5426\u731c\u5230\u8fd9\u4e00\u70b9?](#-lets-see-if-you-can-guess-this\u770b\u770b\u4f60\u80fd\u5426\u731c\u5230\u8fd9\u4e00\u70b9)\n",
+ " - [> Exceeds the limit for integer string conversion/\u6574\u578b\u8f6c\u5b57\u7b26\u4e32\u8d8a\u754c](#-exceeds-the-limit-for-integer-string-conversion\u6574\u578b\u8f6c\u5b57\u7b26\u4e32\u8d8a\u754c)\n",
+ " - [Section: Slippery Slopes/\u6ed1\u5761\u8c2c\u8bef](#section-slippery-slopes\u6ed1\u5761\u8c2c\u8bef)\n",
+ " - [> Modifying a dictionary while iterating over it/\u8fed\u4ee3\u5b57\u5178\u65f6\u7684\u4fee\u6539](#-modifying-a-dictionary-while-iterating-over-it\u8fed\u4ee3\u5b57\u5178\u65f6\u7684\u4fee\u6539)\n",
+ " - [> Stubborn `del` operator/\u575a\u5f3a\u7684 `del` *](#-stubborn-del-operator\u575a\u5f3a\u7684-del-)\n",
+ " - [> The out of scope variable/\u5916\u90e8\u4f5c\u7528\u57df\u53d8\u91cf](#-the-out-of-scope-variable\u5916\u90e8\u4f5c\u7528\u57df\u53d8\u91cf)\n",
+ " - [> Deleting a list item while iterating/\u8fed\u4ee3\u5217\u8868\u65f6\u5220\u9664\u5143\u7d20](#-deleting-a-list-item-while-iterating\u8fed\u4ee3\u5217\u8868\u65f6\u5220\u9664\u5143\u7d20)\n",
+ " - [> Lossy zip of iterators/\u4e22\u4e09\u843d\u56db\u7684zip *](#->-Lossy-zip-of-iterators/\u4e22\u4e09\u843d\u56db\u7684zip-)\n",
+ " - [> Loop variables leaking out!/\u5faa\u73af\u53d8\u91cf\u6cc4\u6f0f!](#-loop-variables-leaking-out\u5faa\u73af\u53d8\u91cf\u6cc4\u6f0f)\n",
+ " - [> Beware of default mutable arguments!/\u5f53\u5fc3\u9ed8\u8ba4\u7684\u53ef\u53d8\u53c2\u6570!](#-beware-of-default-mutable-arguments\u5f53\u5fc3\u9ed8\u8ba4\u7684\u53ef\u53d8\u53c2\u6570)\n",
+ " - [> Catching the Exceptions/\u6355\u83b7\u5f02\u5e38](#-catching-the-exceptions\u6355\u83b7\u5f02\u5e38)\n",
+ " - [> Same operands, different story!/\u540c\u4eba\u4e0d\u540c\u547d!](#-same-operands-different-story\u540c\u4eba\u4e0d\u540c\u547d)\n",
+ " - [> Name resolution ignoring class scope/\u5ffd\u7565\u7c7b\u4f5c\u7528\u57df\u7684\u540d\u79f0\u89e3\u6790](#-name-resolution-ignoring-class-scope\u5ffd\u7565\u7c7b\u4f5c\u7528\u57df\u7684\u540d\u79f0\u89e3\u6790)\n",
+ " - [> Rounding like a banker/\u50cf\u94f6\u884c\u5bb6\u4e00\u6837\u820d\u5165 *](#-rounding-like-a-banker/\u50cf\u94f6\u884c\u5bb6\u4e00\u6837\u820d\u5165-)\n",
+ " - [> Needles in a Haystack/\u5927\u6d77\u635e\u9488](#-needles-in-a-haystack\u5927\u6d77\u635e\u9488)\n",
+ " - [> Splitsies/\u5206\u5272\u51fd\u6570](#-Splitsies\u5206\u5272\u51fd\u6570-)\n",
+ " - [> Wild imports/\u901a\u914d\u7b26\u5bfc\u5165\u65b9\u5f0f *](#-Wild-imports\u901a\u914d\u7b26\u5bfc\u5165\u65b9\u5f0f-)\n",
+ " - [> All sorted?/\u90fd\u6392\u5e8f\u4e86\u5417\uff1f *](#-All-sorted\u90fd\u6392\u5e8f\u4e86\u5417-)\n",
+ " - [> Midnight time doesn't exist?/\u4e0d\u5b58\u5728\u7684\u5348\u591c?](#-midnight-time-doesnt-exist\u4e0d\u5b58\u5728\u7684\u5348\u591c)\n",
+ " - [Section: The Hidden treasures!/\u9690\u85cf\u7684\u5b9d\u85cf!](#section-the-hidden-treasures\u9690\u85cf\u7684\u5b9d\u85cf)\n",
+ " - [> Okay Python, Can you make me fly?/Python, \u53ef\u5426\u5e26\u6211\u98de? *](#-okay-python-can-you-make-me-flypython-\u53ef\u5426\u5e26\u6211\u98de-)\n",
+ " - [> `goto`, but why?/`goto`, \u4f46\u4e3a\u4ec0\u4e48? *](#-goto-but-whygoto-\u4f46\u4e3a\u4ec0\u4e48-)\n",
+ " - [> Brace yourself!/\u505a\u597d\u601d\u60f3\u51c6\u5907 *](#-brace-yourself\u505a\u597d\u601d\u60f3\u51c6\u5907-)\n",
+ " - [> Let's meet Friendly Language Uncle For Life/\u8ba9\u751f\u6d3b\u66f4\u53cb\u597d *](#-lets-meet-friendly-language-uncle-for-life\u8ba9\u751f\u6d3b\u66f4\u53cb\u597d-)\n",
+ " - [> Even Python understands that love is complicated/\u8fdePython\u4e5f\u77e5\u9053\u7231\u662f\u96be\u8a00\u7684 *](#-even-python-understands-that-love-is-complicated\u8fdePython\u4e5f\u77e5\u9053\u7231\u662f\u96be\u8a00\u7684-)\n",
+ " - [> Yes, it exists!/\u662f\u7684, \u5b83\u5b58\u5728!](#-yes-it-exists\u662f\u7684-\u5b83\u5b58\u5728)\n",
+ " - [> Ellipsis/\u7701\u7565 *](#-Ellipsis\u7701\u7565-)\n",
+ " - [> Inpinity/\u65e0\u9650 *](#-inpinity\u65e0\u9650-)\n",
+ " - [> Let's mangle/\u4fee\u9970\u65f6\u95f4! *](#-Lets-mangle\u4fee\u9970\u65f6\u95f4-)\n",
+ " - [Section: Appearances are deceptive!/\u5916\u8868\u662f\u9760\u4e0d\u4f4f\u7684!](#section-appearances-are-deceptive\u5916\u8868\u662f\u9760\u4e0d\u4f4f\u7684)\n",
+ " - [> Skipping lines?/\u8df3\u8fc7\u4e00\u884c?](#-skipping-lines\u8df3\u8fc7\u4e00\u884c)\n",
+ " - [> Teleportation/\u7a7a\u95f4\u79fb\u52a8 *](#-teleportation\u7a7a\u95f4\u79fb\u52a8-)\n",
+ " - [> Well, something is fishy.../\u55ef, \u6709\u4e9b\u53ef\u7591...](#-well-something-is-fishy\u55ef\u6709\u4e9b\u53ef\u7591)\n",
+ " - [Section: Miscellaneous/\u6742\u9879](#section-miscellaneous\u6742\u9879)\n",
+ " - [> `+=` is faster/\u66f4\u5feb\u7684 `+=` ](#--is-faster\u66f4\u5feb\u7684-)\n",
+ " - [> Let's make a giant string!/\u6765\u505a\u4e2a\u5de8\u5927\u7684\u5b57\u7b26\u4e32\u5427!](#-lets-make-a-giant-string\u6765\u505a\u4e2a\u5de8\u5927\u7684\u5b57\u7b26\u4e32\u5427)\n",
+ " - [> Slowing down `dict` lookups/\u8ba9\u5b57\u5178\u7684\u67e5\u627e\u6162\u4e0b\u6765 *](#-Slowing-down-dict-lookups\u8ba9\u5b57\u5178\u7684\u67e5\u627e\u6162\u4e0b\u6765-)\n",
+ " - [> Bloating instance `dict`s/\u53d8\u81c3\u80bf\u7684`dict`\u5b9e\u4f8b\u4eec *](#-Bloating-instance-dicts/\u53d8\u81c3\u80bf\u7684dict\u5b9e\u4f8b\u4eec-)\n",
+ " - [> Minor Ones/\u5c0f\u77e5\u8bc6\u70b9](#-minor-ones\u5c0f\u77e5\u8bc6\u70b9)\n",
+ "- [Contributing/\u8d21\u732e](#contributing\u8d21\u732e)\n",
+ "- [Acknowledgements/\u81f4\u8c22](#acknowledgements\u81f4\u8c22)\n",
+ "- [\ud83c\udf93 License/\u8bb8\u53ef](#-license\u8bb8\u53ef)\n",
+ " - [Help/\u5e2e\u52a9](#help\u5e2e\u52a9)\n",
+ " - [Surprise your geeky pythonist friends?/\u60f3\u7ed9\u4f60\u7684\u6781\u5ba2\u670b\u53cb\u4e00\u4e2a\u60ca\u559c?](#surprise-your-geeky-pythonist-friends\u60f3\u7ed9\u4f60\u7684\u6781\u5ba2\u670b\u53cb\u4e00\u4e2a\u60ca\u559c)\n",
+ " - [Need a pdf version?/\u9700\u8981\u6765\u4e00\u4efdpdf\u7248\u7684?](#need-a-pdf-version\u9700\u8981\u6765\u4e00\u4efdpdf\u7248\u7684)\n",
+ " - [Follow Commit/\u8ffd\u8e2aCommit](#follow-commit\u8ffd\u8e2aCommit)\n",
+ " - [996.icu](#996icu)\n",
+ "\n",
+ "\n",
+ "\n",
+ "# Structure of the Examples/\u793a\u4f8b\u7ed3\u6784\n",
+ "\n",
+ "\u6240\u6709\u793a\u4f8b\u7684\u7ed3\u6784\u90fd\u5982\u4e0b\u6240\u793a:\n",
+ "\n",
+ "> ### > \u4e00\u4e2a\u7cbe\u9009\u7684\u6807\u9898 *\n",
+ "> \u6807\u9898\u672b\u5c3e\u7684\u661f\u53f7\u8868\u793a\u8be5\u793a\u4f8b\u5728\u7b2c\u4e00\u7248\u4e2d\u4e0d\u5b58\u5728\uff0c\u662f\u6700\u8fd1\u6dfb\u52a0\u7684.\n",
+ ">\n",
+ "> ```py\n",
+ "> # \u51c6\u5907\u4ee3\u7801.\n",
+ "> # \u91ca\u653e\u9b54\u6cd5...\n",
+ "> ```\n",
+ ">\n",
+ "> **Output (Python version):**\n",
+ "> ```py\n",
+ "> >>> \u89e6\u53d1\u8bed\u53e5\n",
+ "> \u51fa\u4e4e\u610f\u6599\u7684\u8f93\u51fa\u7ed3\u679c\n",
+ "> ```\n",
+ "> (\u53ef\u9009): \u5bf9\u610f\u5916\u8f93\u51fa\u7ed3\u679c\u7684\u7b80\u77ed\u63cf\u8ff0.\n",
+ ">\n",
+ ">\n",
+ "> #### \ud83d\udca1 \u8bf4\u660e:\n",
+ ">\n",
+ "> * \u7b80\u8981\u8bf4\u660e\u53d1\u751f\u4e86\u4ec0\u4e48\u4ee5\u53ca\u4e3a\u4ec0\u4e48\u4f1a\u53d1\u751f.\n",
+ "> ```py\n",
+ "> \u5982\u6709\u5fc5\u8981, \u4e3e\u4f8b\u8bf4\u660e\n",
+ "> ```\n",
+ "> **Output:**\n",
+ "> ```py\n",
+ "> >>> \u89e6\u53d1\u8bed\u53e5 # \u4e00\u4e9b\u8ba9\u9b54\u6cd5\u53d8\u5f97\u5bb9\u6613\u7406\u89e3\u7684\u4f8b\u5b50\n",
+ "> # \u4e00\u4e9b\u6b63\u5e38\u7684\u8f93\u5165\n",
+ "> ```\n",
+ "\n",
+ "**\u6ce8\u610f:** \u6240\u6709\u7684\u793a\u4f8b\u90fd\u5728 Python 3.5.2 \u7248\u672c\u7684\u4ea4\u4e92\u89e3\u91ca\u5668\u4e0a\u6d4b\u8bd5\u8fc7, \u5982\u679c\u4e0d\u7279\u522b\u8bf4\u660e\u5e94\u8be5\u9002\u7528\u4e8e\u6240\u6709 Python \u7248\u672c.\n",
+ "\n",
+ "# Usage/\u7528\u6cd5\n",
+ "\n",
+ "\u6211\u4e2a\u4eba\u5efa\u8bae, \u6700\u597d\u4f9d\u6b21\u9605\u8bfb\u4e0b\u9762\u7684\u793a\u4f8b, \u5e76\u5bf9\u6bcf\u4e2a\u793a\u4f8b:\n",
+ "- \u4ed4\u7ec6\u9605\u8bfb\u8bbe\u7f6e\u4f8b\u5b50\u6700\u5f00\u59cb\u7684\u4ee3\u7801. \u5982\u679c\u60a8\u662f\u4e00\u4f4d\u7ecf\u9a8c\u4e30\u5bcc\u7684 Python \u7a0b\u5e8f\u5458, \u90a3\u4e48\u5927\u591a\u6570\u65f6\u5019\u60a8\u90fd\u80fd\u6210\u529f\u9884\u671f\u5230\u540e\u9762\u7684\u7ed3\u679c.\n",
+ "- \u9605\u8bfb\u8f93\u51fa\u7ed3\u679c,\n",
+ " + \u786e\u8ba4\u7ed3\u679c\u662f\u5426\u5982\u4f60\u6240\u6599.\n",
+ " + \u786e\u8ba4\u4f60\u662f\u5426\u77e5\u9053\u8fd9\u80cc\u540e\u7684\u539f\u7406.\n",
+ " - \u5982\u679c\u4e0d\u77e5\u9053, \u6df1\u547c\u5438\u7136\u540e\u9605\u8bfb\u8bf4\u660e (\u5982\u679c\u4f60\u8fd8\u662f\u770b\u4e0d\u660e\u767d, \u522b\u6c89\u9ed8! \u53ef\u4ee5\u5728[\u8fd9](https://github.com/satwikkansal/wtfPython)\u63d0\u4e2a issue).\n",
+ " - \u5982\u679c\u77e5\u9053, \u7ed9\u81ea\u5df1\u70b9\u5956\u52b1, \u7136\u540e\u53bb\u770b\u4e0b\u4e00\u4e2a\u4f8b\u5b50.\n",
+ "\n",
+ "PS: \u4f60\u4e5f\u53ef\u4ee5\u5728\u547d\u4ee4\u884c\u9605\u8bfb WTFpython. \u6211\u4eec\u6709 pypi \u5305 \u548c npm \u5305(\u652f\u6301\u4ee3\u7801\u9ad8\u4eae).(\u8bd1: \u8fd9\u4e24\u4e2a\u90fd\u662f\u82f1\u6587\u7248\u7684)\n",
+ "\n",
+ "\u5b89\u88c5 npm \u5305 [`wtfpython`](https://www.npmjs.com/package/wtfpython)\n",
+ "```sh\n",
+ "$ npm install -g wtfpython\n",
+ "```\n",
+ "\n",
+ "\u6216\u8005, \u5b89\u88c5 pypi \u5305 [`wtfpython`](https://pypi.python.org/pypi/wtfpython)\n",
+ "```sh\n",
+ "$ pip install wtfpython -U\n",
+ "```\n",
+ "\n",
+ "\u73b0\u5728, \u5728\u547d\u4ee4\u884c\u4e2d\u8fd0\u884c `wtfpython`, \u4f60\u5c31\u53ef\u4ee5\u5f00\u59cb\u6d4f\u89c8\u4e86.\n",
+ "\n",
+ "---\n",
+ "\n",
+ "# \ud83d\udc40 Examples/\u793a\u4f8b\n",
+ "\n",
+ "\n",
+ "\n\n## \u6258\u7ba1\u7b14\u8bb0\u672c\u6307\u5357\n\n\u8fd9\u53ea\u662f\u901a\u8fc7 jupyter notebook \u6d4f\u89c8 wtfpython \u7684\u5b9e\u9a8c\u6027\u5c1d\u8bd5\u3002\u56e0\u4e3a\u4e00\u4e9b\u793a\u4f8b\u662f\u53ea\u8bfb\u7684\uff1a\n- \u5b83\u4eec\u8981\u4e48\u9700\u8981\u6258\u7ba1\u8fd0\u884c\u65f6\u4e0d\u652f\u6301\u7684 Python \u7248\u672c\u3002\n- \u8981\u4e48\u5b83\u4eec\u65e0\u6cd5\u5728\u6b64\u73af\u5883\u4e2d\u590d\u73b0\u3002\n\n\u9884\u671f\u7684\u8f93\u51fa\u5df2\u7ecf\u5b58\u5728\u4e8e\u4ee3\u7801\u5355\u5143\u4e4b\u540e\u7684\u6298\u53e0\u5355\u5143\u4e2d\u3002 Google colab \u63d0\u4f9b Python2\uff082.7\uff09\u548c Python3\uff083.6\uff0c\u9ed8\u8ba4\uff09\u8fd0\u884c\u73af\u5883\u3002 \u60a8\u53ef\u4ee5\u5728\u8fd9\u4e9b Python2 \u7279\u5b9a\u793a\u4f8b\u4e4b\u95f4\u5207\u6362\u3002 \u5bf9\u4e8e\u7279\u5b9a\u4e8e\u5176\u4ed6\u6b21\u8981\u7248\u672c\u7684\u793a\u4f8b\uff0c\u60a8\u53ef\u4ee5\u7b80\u5355\u5730\u53c2\u8003\u6298\u53e0\u7684\u8f93\u51fa\uff08\u76ee\u524d\u65e0\u6cd5\u5728\u6258\u7ba1\u7b14\u8bb0\u672c\u4e2d\u63a7\u5236\u6b21\u8981\u7248\u672c\uff09\u3002 \u60a8\u53ef\u4ee5\u68c0\u67e5\u5f53\u524d\u7684\u6d3b\u52a8\u7248\u672c\n```py\n>>> import sys\n>>> sys.version\n# Prints out Python version here.\n```\n\n\u8bdd\u867d\u5982\u6b64\uff0c\u5927\u591a\u6570\u793a\u4f8b\u90fd\u6309\u9884\u671f\u5de5\u4f5c\u3002 \u5982\u679c\u60a8\u9047\u5230\u4efb\u4f55\u95ee\u9898\uff0c\u8bf7\u968f\u65f6\u67e5\u9605 wtfpython \u4e0a\u7684\u539f\u59cb\u5185\u5bb9\u5e76\u5728 repo \u4e2d\u521b\u5efa\u95ee\u9898\u3002 \u795d\u541b\u987a\u5229\uff01\n---\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Strings can be tricky sometimes/\u5fae\u5999\u7684\u5b57\u7b26\u4e32 *\n",
+ "1\\.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "140420665652016\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "a = \"some_string\"\n",
+ "id(a)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "140420665652016\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "id(\"some\" + \"_\" + \"string\") # \u6ce8\u610f\u4e24\u4e2a\u7684id\u503c\u662f\u76f8\u540c\u7684.\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "2\\.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True\n",
+ "\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "a = \"wtf\"\n",
+ "b = \"wtf\"\n",
+ "a is b\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "False\n",
+ "\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "a = \"wtf!\"\n",
+ "b = \"wtf!\"\n",
+ "a is b\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True # 3.7 \u7248\u672c\u8fd4\u56de\u7ed3\u679c\u4e3a False.\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "a, b = \"wtf!\", \"wtf!\"\n",
+ "a is b \n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "3\\.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "'a' * 20 is 'aaaaaaaaaaaaaaaaaaaa'\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "False # 3.7 \u7248\u672c\u8fd4\u56de\u7ed3\u679c\u4e3a True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "'a' * 21 is 'aaaaaaaaaaaaaaaaaaaaa'\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\u5f88\u597d\u7406\u89e3, \u5bf9\u5427?\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "- \u8fd9\u4e9b\u884c\u4e3a\u662f\u7531\u4e8e Cpython \u5728\u7f16\u8bd1\u4f18\u5316\u65f6, \u67d0\u4e9b\u60c5\u51b5\u4e0b\u4f1a\u5c1d\u8bd5\u4f7f\u7528\u5df2\u7ecf\u5b58\u5728\u7684\u4e0d\u53ef\u53d8\u5bf9\u8c61\u800c\u4e0d\u662f\u6bcf\u6b21\u90fd\u521b\u5efa\u4e00\u4e2a\u65b0\u5bf9\u8c61. (\u8fd9\u79cd\u884c\u4e3a\u88ab\u79f0\u4f5c\u5b57\u7b26\u4e32\u7684\u9a7b\u7559[string interning])\n",
+ "- \u53d1\u751f\u9a7b\u7559\u4e4b\u540e, \u8bb8\u591a\u53d8\u91cf\u53ef\u80fd\u6307\u5411\u5185\u5b58\u4e2d\u7684\u76f8\u540c\u5b57\u7b26\u4e32\u5bf9\u8c61. (\u4ece\u800c\u8282\u7701\u5185\u5b58)\n",
+ "- \u5728\u4e0a\u9762\u7684\u4ee3\u7801\u4e2d, \u5b57\u7b26\u4e32\u662f\u9690\u5f0f\u9a7b\u7559\u7684. \u4f55\u65f6\u53d1\u751f\u9690\u5f0f\u9a7b\u7559\u5219\u53d6\u51b3\u4e8e\u5177\u4f53\u7684\u5b9e\u73b0. \u8fd9\u91cc\u6709\u4e00\u4e9b\u65b9\u6cd5\u53ef\u4ee5\u7528\u6765\u731c\u6d4b\u5b57\u7b26\u4e32\u662f\u5426\u4f1a\u88ab\u9a7b\u7559:\n",
+ " - \u6240\u6709\u957f\u5ea6\u4e3a 0 \u548c\u957f\u5ea6\u4e3a 1 \u7684\u5b57\u7b26\u4e32\u90fd\u88ab\u9a7b\u7559.\n",
+ " - \u5b57\u7b26\u4e32\u5728\u7f16\u8bd1\u65f6\u88ab\u5b9e\u73b0 (`'wtf'` \u5c06\u88ab\u9a7b\u7559, \u4f46\u662f `''.join(['w', 't', 'f'])` \u5c06\u4e0d\u4f1a\u88ab\u9a7b\u7559)\n",
+ " - \u5b57\u7b26\u4e32\u4e2d\u53ea\u5305\u542b\u5b57\u6bcd\uff0c\u6570\u5b57\u6216\u4e0b\u5212\u7ebf\u65f6\u5c06\u4f1a\u9a7b\u7559. \u6240\u4ee5 `'wtf!'` \u7531\u4e8e\u5305\u542b `!` \u800c\u672a\u88ab\u9a7b\u7559. \u53ef\u4ee5\u5728[\u8fd9\u91cc](https://github.com/python/cpython/blob/3.6/Objects/codeobject.c#L19)\u627e\u5230 CPython \u5bf9\u6b64\u89c4\u5219\u7684\u5b9e\u73b0.\n",
+ "\n",
+ " \n",
+ "\n",
+ "- \u5f53\u5728\u540c\u4e00\u884c\u5c06 `a` \u548c `b` \u7684\u503c\u8bbe\u7f6e\u4e3a `\"wtf!\"` \u7684\u65f6\u5019, Python \u89e3\u91ca\u5668\u4f1a\u521b\u5efa\u4e00\u4e2a\u65b0\u5bf9\u8c61, \u7136\u540e\u540c\u65f6\u5f15\u7528\u7b2c\u4e8c\u4e2a\u53d8\u91cf(\u8bd1: \u4ec5\u9002\u7528\u4e8e3.7\u4ee5\u4e0b, \u8be6\u7ec6\u60c5\u51b5\u8bf7\u770b[\u8fd9\u91cc](https://github.com/leisurelicht/wtfpython-cn/issues/13)). \u5982\u679c\u4f60\u5728\u4e0d\u540c\u7684\u884c\u4e0a\u8fdb\u884c\u8d4b\u503c\u64cd\u4f5c, \u5b83\u5c31\u4e0d\u4f1a\u201c\u77e5\u9053\u201d\u5df2\u7ecf\u6709\u4e00\u4e2a `wtf\uff01` \u5bf9\u8c61 (\u56e0\u4e3a `\"wtf!\"` \u4e0d\u662f\u6309\u7167\u4e0a\u9762\u63d0\u5230\u7684\u65b9\u5f0f\u88ab\u9690\u5f0f\u9a7b\u7559\u7684). \u5b83\u662f\u4e00\u79cd\u7f16\u8bd1\u5668\u4f18\u5316, \u7279\u522b\u9002\u7528\u4e8e\u4ea4\u4e92\u5f0f\u73af\u5883.\n",
+ "- \u5e38\u91cf\u6298\u53e0(constant folding) \u662f Python \u4e2d\u7684\u4e00\u79cd [\u7aa5\u5b54\u4f18\u5316(peephole optimization)](https://en.wikipedia.org/wiki/Peephole_optimization) \u6280\u672f. \u8fd9\u610f\u5473\u7740\u5728\u7f16\u8bd1\u65f6\u8868\u8fbe\u5f0f `'a'*20` \u4f1a\u88ab\u66ff\u6362\u4e3a `'aaaaaaaaaaaaaaaaaaaa'` \u4ee5\u51cf\u5c11\u8fd0\u884c\u65f6\u7684\u65f6\u949f\u5468\u671f. \u53ea\u6709\u957f\u5ea6\u5c0f\u4e8e 20 \u7684\u5b57\u7b26\u4e32\u624d\u4f1a\u53d1\u751f\u5e38\u91cf\u6298\u53e0. (\u4e3a\u5565? \u60f3\u8c61\u4e00\u4e0b\u7531\u4e8e\u8868\u8fbe\u5f0f `'a'*10**10` \u800c\u751f\u6210\u7684 `.pyc` \u6587\u4ef6\u7684\u5927\u5c0f). \u76f8\u5173\u7684\u6e90\u7801\u5b9e\u73b0\u5728[\u8fd9\u91cc](https://github.com/python/cpython/blob/3.6/Python/peephole.c#L288).\n",
+ "- \u5982\u679c\u4f60\u662f\u4f7f\u7528 3.7 \u7248\u672c\u4e2d\u8fd0\u884c\u4e0a\u8ff0\u793a\u4f8b\u4ee3\u7801, \u4f1a\u53d1\u73b0\u90e8\u5206\u4ee3\u7801\u7684\u8fd0\u884c\u7ed3\u679c\u4e0e\u6ce8\u91ca\u8bf4\u660e\u76f8\u540c. \u8fd9\u662f\u56e0\u4e3a\u5728 3.7 \u7248\u672c\u4e2d, \u5e38\u91cf\u6298\u53e0\u5df2\u7ecf\u4ece\u7aa5\u5b54\u4f18\u5316\u5668\u8fc1\u79fb\u81f3\u65b0\u7684 AST \u4f18\u5316\u5668, \u540e\u8005\u53ef\u4ee5\u4ee5\u66f4\u9ad8\u7684\u4e00\u81f4\u6027\u6765\u6267\u884c\u4f18\u5316. (\u7531 Eugene Toder \u548c INADA Naoki \u5728 [bpo-29469](https://bugs.python.org/issue29469) \u548c [bpo-11549](https://bugs.python.org/issue11549) \u4e2d\u8d21\u732e.) \n",
+ "- (\u8bd1: \u4f46\u662f\u5728\u6700\u65b0\u7684 3.8 \u7248\u672c\u4e2d, \u7ed3\u679c\u53c8\u53d8\u56de\u53bb\u4e86. \u867d\u7136 3.8 \u7248\u672c\u548c 3.7 \u7248\u672c\u4e00\u6837, \u90fd\u662f\u4f7f\u7528 AST \u4f18\u5316\u5668. \u76ee\u524d\u4e0d\u786e\u5b9a\u5b98\u65b9\u5bf9 3.8 \u7248\u672c\u7684 AST \u505a\u4e86\u4ec0\u4e48\u8c03\u6574.)\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Be careful with chained operations/\u5c0f\u5fc3\u94fe\u5f0f\u64cd\u4f5c\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "False\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "(False == False) in [False] # \u53ef\u4ee5\u7406\u89e3\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "False\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "False == (False in [False]) # \u53ef\u4ee5\u7406\u89e3\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True\n",
+ "\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "False == False in [False] # \u4e3a\u6bdb?\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "False\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "True is False == False\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True\n",
+ "\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "False is False is False\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "1 > 0 < 1\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "False\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "(1 > 0) < 1\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "False\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "1 > (0 < 1)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "\n",
+ "\u6839\u636e https://docs.python.org/3/reference/expressions.html#comparisons\n",
+ "\n",
+ "> \u5f62\u5f0f\u4e0a, \u5982\u679c a, b, c, ..., y, z \u662f\u8868\u8fbe\u5f0f, \u800c op1, op2, ..., opN \u662f\u6bd4\u8f83\u8fd0\u7b97\u7b26, \u90a3\u4e48\u9664\u4e86\u6bcf\u4e2a\u8868\u8fbe\u5f0f\u6700\u591a\u53ea\u51fa\u73b0\u4e00\u6b21\u4ee5\u5916 a op1 b op2 c ... y opN z \u5c31\u7b49\u4e8e a op1 b and b op2 c and ... y opN z.\n",
+ "\n",
+ "\u867d\u7136\u4e0a\u9762\u7684\u4f8b\u5b50\u4f3c\u4e4e\u5f88\u611a\u8822, \u4f46\u662f\u50cf `a == b == c` \u6216 `0 <= x <= 100` \u5c31\u5f88\u68d2\u4e86.\n",
+ "\n",
+ "* `False is False is False` \u76f8\u5f53\u4e8e `(False is False) and (False is False)`\n",
+ "* `True is False == False` \u76f8\u5f53\u4e8e `(True is False) and (False == False)`, \u7531\u4e8e\u8bed\u53e5\u7684\u7b2c\u4e00\u90e8\u5206 (`True is False`) \u7b49\u4e8e `False`, \u56e0\u6b64\u6574\u4e2a\u8868\u8fbe\u5f0f\u7684\u7ed3\u679c\u4e3a `False`.\n",
+ "* `1 > 0 < 1` \u76f8\u5f53\u4e8e `(1 > 0) and (0 < 1)`, \u6240\u4ee5\u6700\u7ec8\u7ed3\u679c\u4e3a `True`.\n",
+ "* \u8868\u8fbe\u5f0f `(1 > 0) < 1` \u76f8\u5f53\u4e8e `True < 1` \u4e14\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " 1\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " int(True)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " 2\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " True + 1 # \u4e0e\u8fd9\u4e2a\u4f8b\u5b50\u65e0\u5173\uff0c\u53ea\u662f\u5a31\u4e50\u4e00\u4e0b\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ " \u6240\u4ee5, `1 < 1` \u7b49\u4e8e `False`\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > How not to use `is` operator/\u4e3a\u4ec0\u4e48\u4e0d\u4f7f\u7528 `is` \u64cd\u4f5c\u7b26\n",
+ "\u4e0b\u9762\u662f\u4e00\u4e2a\u5728\u4e92\u8054\u7f51\u4e0a\u975e\u5e38\u6709\u540d\u7684\u4f8b\u5b50.\n",
+ "\n",
+ "1\\.\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True\n",
+ "\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "a = 256\n",
+ "b = 256\n",
+ "a is b\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "False\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "a = 257\n",
+ "b = 257\n",
+ "a is b\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "2\\.\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "False\n",
+ "\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "a = []\n",
+ "b = []\n",
+ "a is b\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "a = tuple()\n",
+ "b = tuple()\n",
+ "a is b\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "3\\.\n",
+ "**Output**\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "a, b = 257, 257\n",
+ "a is b\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output (Python 3.7.x specifically)**\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "False\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "a, b = 257, 257\n",
+ "a is b\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "\n",
+ "**`is` \u548c `==` \u7684\u533a\u522b**\n",
+ "\n",
+ "* `is` \u8fd0\u7b97\u7b26\u68c0\u67e5\u4e24\u4e2a\u8fd0\u7b97\u5bf9\u8c61\u662f\u5426\u5f15\u7528\u81ea\u540c\u4e00\u5bf9\u8c61 (\u5373, \u5b83\u68c0\u67e5\u4e24\u4e2a\u8fd0\u7b97\u5bf9\u8c61\u662f\u5426\u76f8\u540c).\n",
+ "* `==` \u8fd0\u7b97\u7b26\u6bd4\u8f83\u4e24\u4e2a\u8fd0\u7b97\u5bf9\u8c61\u7684\u503c\u662f\u5426\u76f8\u7b49.\n",
+ "* \u56e0\u6b64 `is` \u4ee3\u8868\u5f15\u7528\u76f8\u540c, `==` \u4ee3\u8868\u503c\u76f8\u7b49. \u4e0b\u9762\u7684\u4f8b\u5b50\u53ef\u4ee5\u5f88\u597d\u7684\u8bf4\u660e\u8fd9\u70b9,\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " [] == []\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " False\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " [] is [] # \u8fd9\u4e24\u4e2a\u7a7a\u5217\u8868\u4f4d\u4e8e\u4e0d\u540c\u7684\u5185\u5b58\u5730\u5740.\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**`256` \u662f\u4e00\u4e2a\u5df2\u7ecf\u5b58\u5728\u7684\u5bf9\u8c61, \u800c `257` \u4e0d\u662f**\n",
+ "\n",
+ "\u5f53\u4f60\u542f\u52a8Python \u7684\u65f6\u5019, \u6570\u503c\u4e3a `-5` \u5230 `256` \u7684\u5bf9\u8c61\u5c31\u5df2\u7ecf\u88ab\u5206\u914d\u597d\u4e86. \u8fd9\u4e9b\u6570\u5b57\u56e0\u4e3a\u7ecf\u5e38\u88ab\u4f7f\u7528, \u6240\u4ee5\u4f1a\u88ab\u63d0\u524d\u51c6\u5907\u597d.\n",
+ "\n",
+ "Python \u901a\u8fc7\u8fd9\u79cd\u521b\u5efa\u5c0f\u6574\u6570\u6c60\u7684\u65b9\u5f0f\u6765\u907f\u514d\u5c0f\u6574\u6570\u9891\u7e41\u7684\u7533\u8bf7\u548c\u9500\u6bc1\u5185\u5b58\u7a7a\u95f4.\n",
+ "\n",
+ "\u5f15\u7528\u81ea https://docs.python.org/3/c-api/long.html\n",
+ "> \u5f53\u524d\u7684\u5b9e\u73b0\u4e3a-5\u5230256\u4e4b\u95f4\u7684\u6240\u6709\u6574\u6570\u4fdd\u7559\u4e00\u4e2a\u6574\u6570\u5bf9\u8c61\u6570\u7ec4, \u5f53\u4f60\u521b\u5efa\u4e86\u4e00\u4e2a\u8be5\u8303\u56f4\u5185\u7684\u6574\u6570\u65f6, \u4f60\u53ea\u9700\u8981\u8fd4\u56de\u73b0\u6709\u5bf9\u8c61\u7684\u5f15\u7528. \u6240\u4ee5\u6539\u53d81\u7684\u503c\u662f\u6709\u53ef\u80fd\u7684. \u6211\u6000\u7591\u8fd9\u79cd\u884c\u4e3a\u5728Python\u4e2d\u662f\u672a\u5b9a\u4e49\u884c\u4e3a. :-)\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "10922528\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "id(256)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "10922528\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "a = 256\n",
+ "b = 256\n",
+ "id(a)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "10922528\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "id(b)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "140084850247312\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "id(257)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "140084850247440\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "x = 257\n",
+ "y = 257\n",
+ "id(x)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "140084850247344\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "id(y)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\u8fd9\u91cc\u89e3\u91ca\u5668\u5e76\u6ca1\u6709\u667a\u80fd\u5230\u80fd\u5728\u6267\u884c `y = 257` \u65f6\u610f\u8bc6\u5230\u6211\u4eec\u5df2\u7ecf\u521b\u5efa\u4e86\u4e00\u4e2a\u6574\u6570 `257`, \u6240\u4ee5\u5b83\u5728\u5185\u5b58\u4e2d\u53c8\u65b0\u5efa\u4e86\u53e6\u4e00\u4e2a\u5bf9\u8c61.\n",
+ "\n",
+ "\u7c7b\u4f3c\u7684\u4f18\u5316\u4e5f\u9002\u7528\u4e8e\u5176\u4ed6**\u4e0d\u53ef\u53d8**\u5bf9\u8c61\uff0c\u4f8b\u5982\u7a7a\u5143\u7ec4\u3002\u7531\u4e8e\u5217\u8868\u662f\u53ef\u53d8\u7684\uff0c\u8fd9\u5c31\u662f\u4e3a\u4ec0\u4e48 `[] is []` \u5c06\u8fd4\u56de `False` \u800c `() is ()` \u5c06\u8fd4\u56de `True`\u3002 \u8fd9\u89e3\u91ca\u4e86\u6211\u4eec\u7684\u7b2c\u4e8c\u4e2a\u4ee3\u7801\u6bb5\u3002\u800c\u7b2c\u4e09\u4e2a\u5462\uff1a\n",
+ "\n",
+ "**\u5f53 `a` \u548c `b` \u5728\u540c\u4e00\u884c\u4e2d\u4f7f\u7528\u76f8\u540c\u7684\u503c\u521d\u59cb\u5316\u65f6\uff0c\u4f1a\u6307\u5411\u540c\u4e00\u4e2a\u5bf9\u8c61.**\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "140640774013296\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "a, b = 257, 257\n",
+ "id(a)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "140640774013296\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "id(b)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "140640774013392\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "a = 257\n",
+ "b = 257\n",
+ "id(a)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "140640774013488\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "id(b)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "* \u5f53 a \u548c b \u5728\u540c\u4e00\u884c\u4e2d\u88ab\u8bbe\u7f6e\u4e3a `257` \u65f6, Python \u89e3\u91ca\u5668\u4f1a\u521b\u5efa\u4e00\u4e2a\u65b0\u5bf9\u8c61, \u7136\u540e\u540c\u65f6\u5f15\u7528\u7b2c\u4e8c\u4e2a\u53d8\u91cf. \u5982\u679c\u4f60\u5728\u4e0d\u540c\u7684\u884c\u4e0a\u8fdb\u884c, \u5b83\u5c31\u4e0d\u4f1a \"\u77e5\u9053\" \u5df2\u7ecf\u5b58\u5728\u4e00\u4e2a `257` \u5bf9\u8c61\u4e86.\n",
+ "* \u8fd9\u662f\u4e00\u79cd\u7279\u522b\u4e3a\u4ea4\u4e92\u5f0f\u73af\u5883\u505a\u7684\u7f16\u8bd1\u5668\u4f18\u5316. \u5f53\u4f60\u5728\u5b9e\u65f6\u89e3\u91ca\u5668\u4e2d\u8f93\u5165\u4e24\u884c\u7684\u65f6\u5019, \u4ed6\u4eec\u4f1a\u5355\u72ec\u7f16\u8bd1, \u56e0\u6b64\u4e5f\u4f1a\u5355\u72ec\u8fdb\u884c\u4f18\u5316. \u5982\u679c\u4f60\u5728 `.py` \u6587\u4ef6\u4e2d\u5c1d\u8bd5\u8fd9\u4e2a\u4f8b\u5b50, \u5219\u4e0d\u4f1a\u770b\u5230\u76f8\u540c\u7684\u884c\u4e3a, \u56e0\u4e3a\u6587\u4ef6\u662f\u4e00\u6b21\u6027\u7f16\u8bd1\u7684\u3002\u8fd9\u79cd\u4f18\u5316\u4e0d\u4ec5\u9650\u4e8e\u6574\u6570\uff0c\u5b83\u4e5f\u9002\u7528\u4e8e\u5176\u4ed6\u4e0d\u53ef\u53d8\u6570\u636e\u7c7b\u578b\uff0c\u4f8b\u5982\u5b57\u7b26\u4e32\uff08\u67e5\u770b\u793a\u4f8b\u201c\u5fae\u5999\u7684\u5b57\u7b26\u4e32\u201d\uff09\u548c\u6d6e\u70b9\u6570\uff0c\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " a, b = 257.0, 257.0\n",
+ " a is b\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "* \u4e3a\u4ec0\u4e48\u8fd9\u4e0d\u9002\u7528\u4e8e Python 3.7\uff1f \u5927\u6982\u662f\u56e0\u4e3a\u6b64\u7c7b\u7f16\u8bd1\u5668\u4f18\u5316\u662f\u7279\u5b9a\u4e8e\u5b9e\u73b0\u7684\uff08\u5373\u53ef\u80fd\u968f\u7248\u672c\u3001\u64cd\u4f5c\u7cfb\u7edf\u7b49\u800c\u53d8\u5316\uff09\u3002\u6211\u4ecd\u5728\u8bd5\u56fe\u5f04\u6e05\u695a\u5bfc\u81f4\u95ee\u9898\u7684\u5177\u4f53\u5b9e\u73b0\u66f4\u6539\uff0c\u60a8\u53ef\u4ee5\u67e5\u770b\u6b64 [\u95ee\u9898](https://github.com/satwikkansal/wtfpython/issues/100) \u4ee5\u83b7\u53d6\u66f4\u65b0\u3002\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Hash brownies/\u662f\u65f6\u5019\u6765\u70b9\u86cb\u7cd5\u4e86!\n",
+ "* hash brownie\u6307\u4e00\u79cd\u542b\u6709\u5927\u9ebb\u6210\u5206\u7684\u86cb\u7cd5, \u6240\u4ee5\u8fd9\u91cc\u662f\u53e5\u53cc\u5173\n",
+ "* \u8fd9\u91cc\u4fdd\u7559\u539f\u4f5c\u8005\u5bf9\u4e8e\u6807\u9898\u7684\u7ffb\u8bd1\n",
+ "\n",
+ "\n",
+ "\n",
+ "1\\.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "some_dict = {}\n",
+ "some_dict[5.5] = \"JavaScript\"\n",
+ "some_dict[5.0] = \"Ruby\"\n",
+ "some_dict[5] = \"Python\"\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "\"JavaScript\"\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "some_dict[5.5]\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "\"Python\"\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "some_dict[5.0] # \"Python\" \u6d88\u9664\u4e86 \"Ruby\" \u7684\u5b58\u5728?\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "\"Python\"\n",
+ "\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "some_dict[5] \n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "complex\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "complex_five = 5 + 0j\n",
+ "type(complex_five)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "\"Python\"\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "some_dict[complex_five]\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\u4e3a\u4ec0\u4e48\u5230\u5904\u90fd\u662fPython?\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e\n",
+ "\n",
+ "\n",
+ "* \u8fd9\u4e2a StackOverflow\u7684 [\u56de\u7b54](https://stackoverflow.com/a/32211042/4354153) \u6f02\u4eae\u5730\u89e3\u91ca\u4e86\u8fd9\u80cc\u540e\u7684\u57fa\u672c\u539f\u7406.\n",
+ "\n",
+ "* Python \u5b57\u5178\u4e2d\u952e\u7684\u552f\u4e00\u6027\u662f\u6839\u636e *\u7b49\u4ef7\u6027*\uff0c\u800c\u4e0d\u662f\u540c\u4e00\u6027\u3002 \u56e0\u6b64\uff0c\u5373\u4f7f `5`\u3001`5.0` \u548c `5 + 0j` \u662f\u4e0d\u540c\u7c7b\u578b\u7684\u4e0d\u540c\u5bf9\u8c61\uff0c\u7531\u4e8e\u5b83\u4eec\u662f\u76f8\u7b49\u7684\uff0c\u5b83\u4eec\u4e0d\u80fd\u90fd\u5728\u540c\u4e00\u4e2a `dict`\uff08\u6216 `set`\uff09\u4e2d\u3002 \u53ea\u8981\u60a8\u63d2\u5165\u5176\u4e2d\u4efb\u4f55\u4e00\u4e2a\uff0c\u5c1d\u8bd5\u67e5\u627e\u4efb\u4f55\u4e0d\u540c\u4f46\u7b49\u4ef7\u7684\u952e\u90fd\u5c06\u4f7f\u7528\u539f\u59cb\u6620\u5c04\u503c\u6210\u529f\uff08\u800c\u4e0d\u662f\u56e0\u201cKeyError\u201d\u800c\u5931\u8d25\uff09\uff1a\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " 5 == 5.0 == 5 + 0j\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " 5 is not 5.0 is not 5 + 0j\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " some_dict = {}\n",
+ " some_dict[5.0] = \"Ruby\"\n",
+ " 5.0 in some_dict\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " (5 in some_dict) and (5 + 0j in some_dict)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "* \u8fd9\u5728\u8d4b\u503c\u7684\u65f6\u5019\u4e5f\u4f1a\u751f\u6548\u3002\u56e0\u6b64\uff0c\u5f53\u60a8\u6267\u884c `some_dict[5] = \"Python\"` \u65f6\uff0cPython \u4f1a\u627e\u5230\u5177\u6709\u7b49\u4ef7\u952e\u503c `5.0 -> \"Ruby\"` \u7684\u73b0\u6709\u9879\uff0c\u8986\u76d6\u5176\u503c\uff0c\u5e76\u4fdd\u7559\u539f\u59cb\u952e\u503c\u3002\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " {5.0: 'Ruby'}\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " some_dict\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " {5.0: 'Python'}\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " some_dict[5] = \"Python\"\n",
+ " some_dict\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "* \u90a3\u4e48\u6211\u4eec\u5982\u4f55\u5c06\u952e\u503c\u66f4\u65b0\u4e3a`5`\uff08\u800c\u4e0d\u662f`5.0`\uff09\uff1f \u6211\u4eec\u5b9e\u9645\u4e0a\u4e0d\u80fd\u539f\u5730\u66f4\u65b0\uff0c\u4f46\u662f\u6211\u4eec\u53ef\u4ee5\u5148\u5220\u9664\u952e\uff08`del some_dict[5.0]`\uff09\uff0c\u7136\u540e\u91cd\u65b0\u8d4b\u503c\uff08`some_dict[5]`\uff09\u5f97\u5230\u6574\u6570`5` \u4f5c\u4e3a\u952e\u800c\u4e0d\u662f\u6d6e\u70b9\u6570 `5.0`\uff0c\u5c3d\u7ba1\u8fd9\u5c5e\u4e8e\u6781\u5c11\u6570\u60c5\u51b5\u3002\n",
+ "\n",
+ "* Python \u662f\u5982\u4f55\u5728\u5305\u542b `5.0` \u7684\u5b57\u5178\u4e2d\u627e\u5230 `5` \u7684\uff1f Python \u53ea\u9700\u8981\u82b1\u8d39\u5e38\u6570\u65f6\u95f4\uff0c\u800c\u65e0\u9700\u4f7f\u7528\u54c8\u5e0c\u51fd\u6570\u904d\u5386\u6bcf\u4e00\u9879\u3002\u5f53 Python \u5728 dict \u4e2d\u67e5\u627e\u952e `foo` \u65f6\uff0c\u5b83\u9996\u5148\u8ba1\u7b97 `hash(foo)`\uff08\u4ee5\u5e38\u6570\u65f6\u95f4\u8fd0\u884c\uff09\u3002\u56e0\u4e3a\u5728 Python \u4e2d\uff0c\u8981\u6c42\u76f8\u7b49\u7684\u5bf9\u8c61\u5177\u6709\u76f8\u540c\u7684\u54c8\u5e0c\u503c\uff08\u6b64\u5904\u4e3a[\u6587\u6863](https://docs.python.org/3/reference/datamodel.html#object.__hash__)\uff09\uff0c`5` \u3001`5.0` \u548c `5 + 0j` \u5177\u6709\u76f8\u540c\u7684\u54c8\u5e0c\u503c\u3002\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " 5 == 5.0 == 5 + 0j\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " hash(5) == hash(5.0) == hash(5 + 0j)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ " **\u6ce8\u610f\uff1a** \u53cd\u4e4b\u4e0d\u4e00\u5b9a\u6b63\u786e\uff1a\u5177\u6709\u76f8\u7b49\u54c8\u5e0c\u503c\u7684\u5bf9\u8c61\u672c\u8eab\u53ef\u80fd\u4e0d\u76f8\u7b49\u3002\uff08\u8fd9\u662f[\u54c8\u5e0c\u51b2\u7a81](https://en.wikipedia.org/wiki/Collision_(computer_science)\uff09\u9020\u6210\u7684\uff0c\u8fd9\u4e5f\u4f1a\u964d\u4f4e\u54c8\u5e0c\u8fd0\u7b97\u7684\u6027\u80fd\u3002\uff09\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Deep down, we're all the same./\u672c\u8d28\u4e0a,\u6211\u4eec\u90fd\u4e00\u6837. *\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "class WTF:\n",
+ " pass\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "False\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "WTF() == WTF() # \u4e24\u4e2a\u4e0d\u540c\u7684\u5bf9\u8c61\u5e94\u8be5\u4e0d\u76f8\u7b49\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "False\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "WTF() is WTF() # \u4e5f\u4e0d\u76f8\u540c\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "hash(WTF()) == hash(WTF()) # \u54c8\u5e0c\u503c\u4e5f\u5e94\u8be5\u4e0d\u540c\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "id(WTF()) == id(WTF())\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "\n",
+ "* \u5f53\u8c03\u7528 `id` \u51fd\u6570\u65f6, Python \u521b\u5efa\u4e86\u4e00\u4e2a `WTF` \u7c7b\u7684\u5bf9\u8c61\u5e76\u4f20\u7ed9 `id` \u51fd\u6570. \u7136\u540e `id` \u51fd\u6570\u83b7\u53d6\u5176id\u503c (\u4e5f\u5c31\u662f\u5185\u5b58\u5730\u5740), \u7136\u540e\u4e22\u5f03\u8be5\u5bf9\u8c61. \u8be5\u5bf9\u8c61\u5c31\u88ab\u9500\u6bc1\u4e86.\n",
+ "* \u5f53\u6211\u4eec\u8fde\u7eed\u4e24\u6b21\u8fdb\u884c\u8fd9\u4e2a\u64cd\u4f5c\u65f6, Python\u4f1a\u5c06\u76f8\u540c\u7684\u5185\u5b58\u5730\u5740\u5206\u914d\u7ed9\u7b2c\u4e8c\u4e2a\u5bf9\u8c61. \u56e0\u4e3a (\u5728CPython\u4e2d) `id` \u51fd\u6570\u4f7f\u7528\u5bf9\u8c61\u7684\u5185\u5b58\u5730\u5740\u4f5c\u4e3a\u5bf9\u8c61\u7684id\u503c, \u6240\u4ee5\u4e24\u4e2a\u5bf9\u8c61\u7684id\u503c\u662f\u76f8\u540c\u7684.\n",
+ "* \u7efc\u4e0a, \u5bf9\u8c61\u7684id\u503c\u4ec5\u4ec5\u5728\u5bf9\u8c61\u7684\u751f\u547d\u5468\u671f\u5185\u552f\u4e00. \u5728\u5bf9\u8c61\u88ab\u9500\u6bc1\u4e4b\u540e, \u6216\u88ab\u521b\u5efa\u4e4b\u524d, \u5176\u4ed6\u5bf9\u8c61\u53ef\u4ee5\u5177\u6709\u76f8\u540c\u7684id\u503c.\n",
+ "* \u90a3\u4e3a\u4ec0\u4e48 `is` \u64cd\u4f5c\u7684\u7ed3\u679c\u4e3a `False` \u5462? \u8ba9\u6211\u4eec\u770b\u770b\u8fd9\u6bb5\u4ee3\u7801.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " class WTF(object):\n",
+ " def __init__(self): print(\"I\")\n",
+ " def __del__(self): print(\"D\")\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ " **Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " I\n",
+ " I\n",
+ " D\n",
+ " D\n",
+ " False\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " WTF() is WTF()\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " I\n",
+ " D\n",
+ " I\n",
+ " D\n",
+ " True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " id(WTF()) == id(WTF())\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ " \u6b63\u5982\u4f60\u6240\u770b\u5230\u7684, \u5bf9\u8c61\u9500\u6bc1\u7684\u987a\u5e8f\u662f\u9020\u6210\u6240\u6709\u4e0d\u540c\u4e4b\u5904\u7684\u539f\u56e0.\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Disorder within order/\u6709\u5e8f\u4e2d\u6f5c\u85cf\u7740\u65e0\u5e8f *\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "from collections import OrderedDict\n",
+ "\n",
+ "dictionary = dict()\n",
+ "dictionary[1] = 'a'; dictionary[2] = 'b';\n",
+ "\n",
+ "ordered_dict = OrderedDict()\n",
+ "ordered_dict[1] = 'a'; ordered_dict[2] = 'b';\n",
+ "\n",
+ "another_ordered_dict = OrderedDict()\n",
+ "another_ordered_dict[2] = 'b'; another_ordered_dict[1] = 'a';\n",
+ "\n",
+ "class DictWithHash(dict):\n",
+ " \"\"\"\n",
+ " \u5b9e\u73b0\u4e86 __hash__ \u9b54\u6cd5\u65b9\u6cd5\u7684dict\u7c7b\n",
+ " \"\"\"\n",
+ " __hash__ = lambda self: 0\n",
+ "\n",
+ "class OrderedDictWithHash(OrderedDict):\n",
+ " \"\"\"\n",
+ " \u5b9e\u73b0\u4e86 __hash__ \u9b54\u6cd5\u65b9\u6cd5\u7684OrderedDict\u7c7b\n",
+ " \"\"\"\n",
+ " __hash__ = lambda self: 0\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "dictionary == ordered_dict # \u5982\u679c a == b\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "dictionary == another_ordered_dict # \u4e14 b == c\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "False\n",
+ "\n",
+ "# \u4f17\u6240\u5468\u77e5\uff0cset\u6570\u636e\u7ed3\u6784\u50a8\u5b58\u4e0d\u91cd\u590d\u5143\u7d20\uff0c\n",
+ "# \u8ba9\u6211\u4eec\u751f\u6210\u4ee5\u4e0a\u5b57\u5178\u7684 set \u6570\u636e\u7c7b\u578b\uff0c\u770b\u770b\u4f1a\u53d1\u751f\u4ec0\u4e48\u2026\u2026\n",
+ "\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "ordered_dict == another_ordered_dict # \u90a3\u4e48\u4e3a\u4ec0\u4e48 c == a \u4e0d\u6210\u7acb??\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "Traceback (most recent call last):\n",
+ " File \"\", line 1, in \n",
+ "TypeError: unhashable type: 'dict'\n",
+ "\n",
+ "# dict\u7c7b\u6ca1\u6709\u5b9e\u73b0 __hash__ \uff0c\u51fa\u9519\u53ef\u4ee5\u7406\u89e3\uff0c\u63a5\u4e0b\u6765\u4f7f\u7528\u6211\u4eec\u6d3e\u751f\u7684\u7c7b\u3002\n",
+ "\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "len({dictionary, ordered_dict, another_ordered_dict})\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "1\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "dictionary = DictWithHash()\n",
+ "dictionary[1] = 'a'; dictionary[2] = 'b';\n",
+ "ordered_dict = OrderedDictWithHash()\n",
+ "ordered_dict[1] = 'a'; ordered_dict[2] = 'b';\n",
+ "another_ordered_dict = OrderedDictWithHash()\n",
+ "another_ordered_dict[2] = 'b'; another_ordered_dict[1] = 'a';\n",
+ "len({dictionary, ordered_dict, another_ordered_dict})\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "2\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "len({ordered_dict, another_ordered_dict, dictionary}) # \u4ea4\u6362\u987a\u5e8f\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\u5230\u5e95\u53d1\u751f\u4e86\u4ec0\u4e48?\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "\n",
+ "- \u7b49\u53f7\u7684\u4f20\u9012\u6027\u6ca1\u6709\u5728 `dictionary`, `ordered_dict` \u548c `another_ordered_dict` \u4e4b\u95f4\u751f\u6548\u662f `OrderedDict` \u7c7b\u4e2d `__eq__` \u65b9\u6cd5\u7684\u5b9e\u73b0\u65b9\u5f0f\u9020\u6210\u7684\u3002\u6839\u636e[\u6587\u6863](https://docs.python.org/3/library/collections.html#ordereddict-objects)\u4ee5\u4e0b\u90e8\u5206:\n",
+ " \n",
+ " > \u5bf9\u4e8e `OrderedDict` \u7c7b\u4e4b\u95f4\uff0c\u76f8\u7b49\u6027\u7684\u5224\u5b9a\u662f\u4f4d\u7f6e\u654f\u611f\u7684\uff0c\u5b9e\u73b0\u7c7b\u4f3c\u4e8e `list(od1.items())==list(od2.items())`\u3002\u5bf9\u4e8e `OrderedDict` \u7c7b\u4e0e\u5176\u4ed6 `Mapping` \u5bf9\u8c61\uff08\u4f8b\u5982`dict` \u7c7b\uff09\uff0c\u76f8\u7b49\u6027\u7684\u5224\u5b9a\u662f\u975e\u4f4d\u7f6e\u654f\u611f\u7684\u3002\n",
+ "- \u8fd9\u662f\u4e3a\u4e86\u4efb\u4f55\u4f7f\u7528\u5e38\u89c4 `dict` \u7c7b\u7684\u5730\u65b9\u80fd\u591f\u76f4\u63a5\u4f7f\u7528 `OrderedDict` \u5bf9\u8c61\u4ee3\u66ff\u3002\n",
+ "- \u597d\u5566\uff0c\u90a3\u4e3a\u4ec0\u4e48\u6539\u53d8\u987a\u5e8f\u4f1a\u5f71\u54cd `set` \u5bf9\u8c61\u751f\u6210\u7684\u957f\u5ea6\u5462? \u7b54\u6848\u5c31\u662f\u4e0a\u9762\u8bf4\u7684\u7f3a\u4e4f\u7b49\u53f7\u7684\u4f20\u9012\u6027\u3002\u56e0\u4e3a `set` \u7c7b\u662f\u552f\u4e00\u5143\u7d20\u7684\u65e0\u5e8f\u96c6\u5408\uff0c\u5143\u7d20\u63d2\u5165\u7684\u987a\u5e8f\u4e0d\u5e94\u8be5\u6709\u5f71\u54cd\u3002\u4f46\u5728\u6b64\u4f8b\u4e2d\uff0c\u786e\u6709\u4e0d\u540c\u3002\u8ba9\u6211\u4eec\u8fdb\u4e00\u6b65\u6df1\u5165\u3002\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " some_set = set()\n",
+ " some_set.add(dictionary) # \u6d89\u53ca\u7684\u53d8\u91cf\u662f\u524d\u5e8f\u7247\u6bb5\u5b9a\u4e49\u7684 mapping \u5bf9\u8c61\n",
+ " ordered_dict in some_set\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " 1\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " some_set.add(ordered_dict)\n",
+ " len(some_set)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " another_ordered_dict in some_set\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " 1\n",
+ "\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " some_set.add(another_ordered_dict)\n",
+ " len(some_set)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " False\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " another_set = set()\n",
+ " another_set.add(ordered_dict)\n",
+ " another_ordered_dict in another_set\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " 2\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " another_set.add(another_ordered_dict)\n",
+ " len(another_set)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " dictionary in another_set\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " 2\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " another_set.add(another_ordered_dict)\n",
+ " len(another_set)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ " \u56e0\u6b64\uff0c\u4e0d\u4e00\u81f4\u6027\u662f\u7531\u4e8e `another_ordered_dict in another_set` \u7ed3\u679c\u4e3a `False`\u3002 \u56e0\u4e3a `ordered_dict` \u5df2\u7ecf\u5728 `another_set` \u4e2d\uff0c\u4f46\u5982\u524d\u6240\u8ff0\uff0c `ordered_dict == another_ordered_dict` \u7684\u7ed3\u679c\u4e3a `False`\uff0c\u4f1a\u5728\u540e\u7eed\u518d\u52a0\u5165 `another_ordered_dict` \u5230 `another_set` \u4e2d\u3002\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Keep trying.../\u4e0d\u505c\u7684try *\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "def some_func():\n",
+ " try:\n",
+ " return 'from_try'\n",
+ " finally:\n",
+ " return 'from_finally'\n",
+ "\n",
+ "def another_func(): \n",
+ " for _ in range(3):\n",
+ " try:\n",
+ " continue\n",
+ " finally:\n",
+ " print(\"Finally!\")\n",
+ "\n",
+ "def one_more_func(): # A gotcha!\n",
+ " try:\n",
+ " for i in range(3):\n",
+ " try:\n",
+ " 1 / i\n",
+ " except ZeroDivisionError:\n",
+ " # Let's throw it here and handle it outside for loop\n",
+ " raise ZeroDivisionError(\"A trivial divide by zero error\")\n",
+ " finally:\n",
+ " print(\"Iteration\", i)\n",
+ " break\n",
+ " except ZeroDivisionError as e:\n",
+ " print(\"Zero division error occurred\", e)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "'from_finally'\n",
+ "\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "some_func()\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "Finally!\n",
+ "Finally!\n",
+ "Finally!\n",
+ "\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "another_func()\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "Traceback (most recent call last):\n",
+ " File \"\", line 1, in \n",
+ "ZeroDivisionError: division by zero\n",
+ "\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "1 / 0\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "Iteration 0\n",
+ "\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "one_more_func()\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "\n",
+ "- \u5f53\u5728 \"try...finally\" \u8bed\u53e5\u7684 `try` \u4e2d\u6267\u884c `return`, `break` \u6216 `continue` \u540e, `finally` \u5b50\u53e5\u4f9d\u7136\u4f1a\u6267\u884c.\n",
+ "- \u51fd\u6570\u7684\u8fd4\u56de\u503c\u7531\u6700\u540e\u6267\u884c\u7684 `return` \u8bed\u53e5\u51b3\u5b9a. \u7531\u4e8e `finally` \u5b50\u53e5\u4e00\u5b9a\u4f1a\u6267\u884c, \u6240\u4ee5 `finally` \u5b50\u53e5\u4e2d\u7684 `return` \u5c06\u59cb\u7ec8\u662f\u6700\u540e\u6267\u884c\u7684\u8bed\u53e5.\n",
+ "- \u8fd9\u91cc\u9700\u8981\u6ce8\u610f\u7684\u662f\uff0c\u5982\u679c finally \u5b50\u53e5\u6267\u884c `return` \u6216 `break` \u8bed\u53e5\uff0c\u4e34\u65f6\u4fdd\u5b58\u7684\u5f02\u5e38\u5c06\u88ab\u4e22\u5f03\u3002\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > For what?/\u4e3a\u4ec0\u4e48?\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "some_string = \"wtf\"\n",
+ "some_dict = {}\n",
+ "for i, some_dict[i] in enumerate(some_string):\n",
+ " pass\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{0: 'w', 1: 't', 2: 'f'}\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "some_dict # \u521b\u5efa\u4e86\u7d22\u5f15\u5b57\u5178.\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "\n",
+ "* [Python \u8bed\u6cd5](https://docs.python.org/3/reference/grammar.html) \u4e2d\u5bf9 `for` \u7684\u5b9a\u4e49\u662f:\n",
+ " ```\n",
+ " for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite]\n",
+ " ```\n",
+ " \u5176\u4e2d `exprlist` \u6307\u5206\u914d\u76ee\u6807. \u8fd9\u610f\u5473\u7740\u5bf9\u53ef\u8fed\u4ee3\u5bf9\u8c61\u4e2d\u7684**\u6bcf\u4e00\u9879\u90fd\u4f1a\u6267\u884c**\u7c7b\u4f3c `{exprlist} = {next_value}` \u7684\u64cd\u4f5c.\n",
+ "\n",
+ " \u4e00\u4e2a\u6709\u8da3\u7684\u4f8b\u5b50\u8bf4\u660e\u4e86\u8fd9\u4e00\u70b9:\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " for i in range(4):\n",
+ " print(i)\n",
+ " i = 10\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ " **Output:**\n",
+ " ```\n",
+ " 0\n",
+ " 1\n",
+ " 2\n",
+ " 3\n",
+ " ```\n",
+ "\n",
+ " \u4f60\u53ef\u66fe\u89c9\u5f97\u8fd9\u4e2a\u5faa\u73af\u53ea\u4f1a\u8fd0\u884c\u4e00\u6b21?\n",
+ "\n",
+ " **\ud83d\udca1 \u8bf4\u660e:**\n",
+ "\n",
+ " - \u7531\u4e8e\u5faa\u73af\u5728Python\u4e2d\u5de5\u4f5c\u65b9\u5f0f, \u8d4b\u503c\u8bed\u53e5 `i = 10` \u5e76\u4e0d\u4f1a\u5f71\u54cd\u8fed\u4ee3\u5faa\u73af, \u5728\u6bcf\u6b21\u8fed\u4ee3\u5f00\u59cb\u4e4b\u524d, \u8fed\u4ee3\u5668(\u8fd9\u91cc\u6307 `range(4)`) \u751f\u6210\u7684\u4e0b\u4e00\u4e2a\u5143\u7d20\u5c31\u88ab\u89e3\u5305\u5e76\u8d4b\u503c\u7ed9\u76ee\u6807\u5217\u8868\u7684\u53d8\u91cf(\u8fd9\u91cc\u6307 `i`)\u4e86.\n",
+ "\n",
+ "* \u5728\u6bcf\u4e00\u6b21\u7684\u8fed\u4ee3\u4e2d, `enumerate(some_string)` \u51fd\u6570\u5c31\u751f\u6210\u4e00\u4e2a\u65b0\u503c `i` (\u8ba1\u6570\u5668\u589e\u52a0) \u5e76\u4ece `some_string` \u4e2d\u83b7\u53d6\u4e00\u4e2a\u5b57\u7b26. \u7136\u540e\u5c06\u5b57\u5178 `some_dict` \u952e `i` (\u521a\u521a\u5206\u914d\u7684) \u7684\u503c\u8bbe\u4e3a\u8be5\u5b57\u7b26. \u672c\u4f8b\u4e2d\u5faa\u73af\u7684\u5c55\u5f00\u53ef\u4ee5\u7b80\u5316\u4e3a:\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " i, some_dict[i] = (0, 'w')\n",
+ " i, some_dict[i] = (1, 't')\n",
+ " i, some_dict[i] = (2, 'f')\n",
+ " some_dict\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Evaluation time discrepancy/\u6267\u884c\u65f6\u673a\u5dee\u5f02\n",
+ "1\\.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "array = [1, 8, 15]\n",
+ "# \u4e00\u4e2a\u5178\u578b\u7684\u751f\u6210\u5668\u8868\u8fbe\u5f0f\n",
+ "g = (x for x in array if array.count(x) > 0)\n",
+ "array = [2, 8, 22]\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "collapsed": true
+ },
+ "execution_count": null,
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "[8]\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(list(g)) #\u5176\u4ed6\u7684\u503c\u53bb\u54ea\u513f\u4e86\uff1f\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "2\\.\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "array_1 = [1,2,3,4]\n",
+ "g1 = (x for x in array_1)\n",
+ "array_1 = [1,2,3,4,5]\n",
+ "\n",
+ "array_2 = [1,2,3,4]\n",
+ "g2 = (x for x in array_2)\n",
+ "array_2[:] = [1,2,3,4,5]\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "collapsed": true
+ },
+ "execution_count": null,
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "[1,2,3,4]\n",
+ "\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(list(g1))\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "collapsed": true
+ },
+ "execution_count": null,
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "[1,2,3,4,5]\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(list(g2))\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "3\\.\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "array_3 = [1, 2, 3]\n",
+ "array_4 = [10, 20, 30]\n",
+ "gen = (i + j for i in array_3 for j in array_4)\n",
+ "\n",
+ "array_3 = [4, 5, 6]\n",
+ "array_4 = [400, 500, 600]\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "collapsed": true
+ },
+ "execution_count": null,
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "[401, 501, 601, 402, 502, 602, 403, 503, 603]\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(list(gen))\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e\n",
+ "\n",
+ "- \u5728[\u751f\u6210\u5668](https://wiki.python.org/moin/Generators)\u8868\u8fbe\u5f0f\u4e2d, `in` \u5b50\u53e5\u5728\u58f0\u660e\u65f6\u6267\u884c, \u800c\u6761\u4ef6\u5b50\u53e5\u5219\u662f\u5728\u8fd0\u884c\u65f6\u6267\u884c.\n",
+ "- \u6240\u4ee5\u5728\u8fd0\u884c\u524d, `array` \u5df2\u7ecf\u88ab\u91cd\u65b0\u8d4b\u503c\u4e3a `[2, 8, 22]`, \u56e0\u6b64\u5bf9\u4e8e\u4e4b\u524d\u7684 `1`, `8` \u548c `15`, \u53ea\u6709 `count(8)` \u7684\u7ed3\u679c\u662f\u5927\u4e8e `0` \u7684, \u6240\u4ee5\u751f\u6210\u5668\u53ea\u4f1a\u751f\u6210 `8`.\n",
+ "- \u7b2c\u4e8c\u90e8\u5206\u4e2d `g1` \u548c `g2` \u7684\u8f93\u51fa\u5dee\u5f02\u5219\u662f\u7531\u4e8e\u53d8\u91cf `array_1` \u548c `array_2` \u88ab\u91cd\u65b0\u8d4b\u503c\u7684\u65b9\u5f0f\u5bfc\u81f4\u7684.\n",
+ "- \u5728\u7b2c\u4e00\u79cd\u60c5\u51b5\u4e0b, `array_1` \u88ab\u7ed1\u5b9a\u5230\u65b0\u5bf9\u8c61 `[1,2,3,4,5]`, \u56e0\u4e3a `in` \u5b50\u53e5\u662f\u5728\u58f0\u660e\u65f6\u88ab\u6267\u884c\u7684\uff0c \u6240\u4ee5\u5b83\u4ecd\u7136\u5f15\u7528\u65e7\u5bf9\u8c61 `[1,2,3,4]`(\u5e76\u6ca1\u6709\u88ab\u9500\u6bc1).\n",
+ "- \u5728\u7b2c\u4e8c\u79cd\u60c5\u51b5\u4e0b, \u5bf9 `array_2` \u7684\u5207\u7247\u8d4b\u503c\u5c06\u76f8\u540c\u7684\u65e7\u5bf9\u8c61 `[1,2,3,4]` \u539f\u5730\u66f4\u65b0\u4e3a `[1,2,3,4,5]`. \u56e0\u6b64 `g2` \u548c `array_2` \u4ecd\u7136\u5f15\u7528\u540c\u4e00\u4e2a\u5bf9\u8c61(\u8fd9\u4e2a\u5bf9\u8c61\u73b0\u5728\u5df2\u7ecf\u66f4\u65b0\u4e3a `[1,2,3,4,5]`).\n",
+ "- \u597d\u5566\uff0c\u6309\u7167\u76ee\u524d\u8ba8\u8bba\u7684\u903b\u8f91\uff0c\u7b2c\u4e09\u4e2a\u4ee3\u7801\u6bb5\u4e2d\u7684 `list(gen)` \u7684\u503c\u4e0d\u5e94\u8be5\u662f `[11, 21, 31, 12, 22, 32, 13, 23, 33]` \u5417? \uff08\u6bd5\u7adf `array_3` \u548c `array_4` \u7684\u884c\u4e3a\u4e0e `array_1` \u4e00\u6837\uff09\u3002 [PEP-289](https://www.python.org/dev/peps/pep-0289/#the-details) \u4e2d\u89e3\u91ca\u4e86\uff08\u53ea\u6709\uff09`array_4` \u503c\u66f4\u65b0\u7684\u539f\u56e0\n",
+ " > \u53ea\u6709\u6700\u5916\u5c42\u7684 for \u8868\u8fbe\u5f0f\u4f1a\u7acb\u5373\u8ba1\u7b97\uff0c\u5176\u4ed6\u8868\u8fbe\u5f0f\u4f1a\u5ef6\u8fdf\u5230\u751f\u6210\u5668\u8fd0\u884c\u3002\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > `is not ...` is not `is (not ...)`/`is not ...` \u4e0d\u662f `is (not ...)`\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "'something' is not None\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "False\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "'something' is (not None)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "\n",
+ "- `is not` \u662f\u4e2a\u5355\u72ec\u7684\u4e8c\u5143\u8fd0\u7b97\u7b26, \u4e0e\u5206\u522b\u4f7f\u7528 `is` \u548c `not` \u4e0d\u540c.\n",
+ "- \u5982\u679c\u64cd\u4f5c\u7b26\u4e24\u4fa7\u7684\u53d8\u91cf\u6307\u5411\u540c\u4e00\u4e2a\u5bf9\u8c61, \u5219 `is not` \u7684\u7ed3\u679c\u4e3a `False`, \u5426\u5219\u7ed3\u679c\u4e3a `True`.\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > A tic-tac-toe where X wins in the first attempt!/\u4e00\u8e74\u5373\u81f3!\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "# \u6211\u4eec\u5148\u521d\u59cb\u5316\u4e00\u4e2a\u53d8\u91cfrow\n",
+ "row = [\"\"]*3 #row i['', '', '']\n",
+ "# \u5e76\u521b\u5efa\u4e00\u4e2a\u53d8\u91cfboard\n",
+ "board = [row]*3\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[['', '', ''], ['', '', ''], ['', '', '']]\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "board\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "['', '', '']\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "board[0]\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "''\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "board[0][0]\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[['X', '', ''], ['X', '', ''], ['X', '', '']]\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "board[0][0] = \"X\"\n",
+ "board\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\u6211\u4eec\u6709\u6ca1\u6709\u8d4b\u503c\u8fc73\u4e2a \"X\" \u5462\uff1f\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "\n",
+ "\u5f53\u6211\u4eec\u521d\u59cb\u5316 `row` \u53d8\u91cf\u65f6, \u4e0b\u9762\u8fd9\u5f20\u56fe\u5c55\u793a\u4e86\u5185\u5b58\u4e2d\u7684\u60c5\u51b5\u3002\n",
+ "\n",
+ "![image](/images/tic-tac-toe/after_row_initialized.png)\n",
+ "\n",
+ "\u800c\u5f53\u901a\u8fc7\u5bf9 `row` \u505a\u4e58\u6cd5\u6765\u521d\u59cb\u5316 `board` \u65f6, \u5185\u5b58\u4e2d\u7684\u60c5\u51b5\u5219\u5982\u4e0b\u56fe\u6240\u793a (\u6bcf\u4e2a\u5143\u7d20 `board[0]`, `board[1]` \u548c `board[2]` \u90fd\u548c `row` \u4e00\u6837\u5f15\u7528\u4e86\u540c\u4e00\u5217\u8868.)\n",
+ "\n",
+ "![image](/images/tic-tac-toe/after_board_initialized.png)\n",
+ "\n",
+ "\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7\u4e0d\u4f7f\u7528\u53d8\u91cf `row` \u751f\u6210 `board` \u6765\u907f\u514d\u8fd9\u79cd\u60c5\u51b5. ([\u8fd9\u4e2a](https://github.com/satwikkansal/wtfpython/issues/68)issue\u63d0\u51fa\u4e86\u8fd9\u4e2a\u9700\u6c42.)\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[['X', '', ''], ['', '', ''], ['', '', '']]\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "board = [['']*3 for _ in range(3)]\n",
+ "board[0][0] = \"X\"\n",
+ "board\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Schr\u00f6dinger's variable/\u859b\u5b9a\u8c14\u7684\u53d8\u91cf *\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "funcs = []\n",
+ "results = []\n",
+ "for x in range(7):\n",
+ " def some_func():\n",
+ " return x\n",
+ " funcs.append(some_func)\n",
+ " results.append(some_func()) # \u6ce8\u610f\u8fd9\u91cc\u51fd\u6570\u88ab\u6267\u884c\u4e86\n",
+ "\n",
+ "funcs_results = [func() for func in funcs]\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[0, 1, 2, 3, 4, 5, 6]\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "results\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[6, 6, 6, 6, 6, 6, 6]\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "funcs_results\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\u5373\u4f7f\u6bcf\u6b21\u5728\u8fed\u4ee3\u4e2d\u5c06 `some_func` \u52a0\u5165 `funcs` \u524d\u7684 `x` \u503c\u90fd\u4e0d\u76f8\u540c, \u6240\u6709\u7684\u51fd\u6570\u8fd8\u662f\u90fd\u8fd4\u56de6.\n",
+ "\n",
+ "// \u518d\u6362\u4e2a\u4f8b\u5b50\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[512, 512, 512, 512, 512, 512, 512, 512, 512, 512]\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "powers_of_x = [lambda x: x**i for i in range(10)]\n",
+ "[f(2) for f in powers_of_x]\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "\n",
+ "- \u5f53\u5728\u5faa\u73af\u5185\u90e8\u5b9a\u4e49\u4e00\u4e2a\u51fd\u6570\u65f6, \u5982\u679c\u8be5\u51fd\u6570\u5728\u5176\u4e3b\u4f53\u4e2d\u4f7f\u7528\u4e86\u5faa\u73af\u53d8\u91cf, \u5219\u95ed\u5305\u51fd\u6570\u5c06\u4e0e\u5faa\u73af\u53d8\u91cf\u7ed1\u5b9a, \u800c\u4e0d\u662f\u5b83\u7684\u503c. \u56e0\u6b64, \u6240\u6709\u7684\u51fd\u6570\u90fd\u662f\u4f7f\u7528\u6700\u540e\u5206\u914d\u7ed9\u53d8\u91cf\u7684\u503c\u6765\u8fdb\u884c\u8ba1\u7b97\u7684.\n",
+ "\n",
+ "- \u53ef\u4ee5\u901a\u8fc7\u5c06\u5faa\u73af\u53d8\u91cf\u4f5c\u4e3a\u547d\u540d\u53d8\u91cf\u4f20\u9012\u7ed9\u51fd\u6570\u6765\u83b7\u5f97\u9884\u671f\u7684\u7ed3\u679c. **\u4e3a\u4ec0\u4e48\u8fd9\u6837\u53ef\u884c?** \u56e0\u4e3a\u8fd9\u4f1a\u5728\u51fd\u6570\u5185\u518d\u6b21\u5b9a\u4e49\u4e00\u4e2a\u5c40\u90e8\u53d8\u91cf\u3002\u6211\u4eec\u53ef\u4ee5\u770b\u5230\u5b83\u4f7f\u7528\u4e86\u6765\u81ea\u4e0a\u4e0b\u6587\u7684`x`\uff08\u5373*\u4e0d\u662f*\u5c40\u90e8\u53d8\u91cf\uff09\uff1a\n",
+ "\uff08\u8bd1\u8005\u6ce8: inspect\u4f4d\u4e8ePython\u6807\u51c6\u5e93\u4e2d\uff0c\u8be5\u6a21\u5757\u7528\u4e8e\u6536\u96c6python\u5bf9\u8c61\u7684\u4fe1\u606f\uff0c\u53ef\u4ee5\u83b7\u53d6\u7c7b\u6216\u51fd\u6570\u7684\u53c2\u6570\u7684\u4fe1\u606f\uff0c\u6e90\u7801\uff0c\u89e3\u6790\u5806\u6808\uff0c\u5bf9\u5bf9\u8c61\u8fdb\u884c\u7c7b\u578b\u68c0\u67e5\u7b49\u7b49\uff0cPython3.3+\u7248\u672c\u652f\u6301getclosurevars\u51fd\u6570\uff09\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "ClosureVars(nonlocals={}, globals={'x': 6}, builtins={}, unbound=set())\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "import inspect\n",
+ "inspect.getclosurevars(funcs[0])\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\u7531\u4e8e `x` \u662f\u4e00\u4e2a\u5168\u5c40\u503c\uff0c\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7\u66f4\u65b0 `x` \u6765\u66f4\u6539 `funcs` \u7528\u6765\u67e5\u627e\u548c\u8fd4\u56de\u7684\u503c\uff1a\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[42, 42, 42, 42, 42, 42, 42]\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "x = 42\n",
+ "[func() for func in funcs]\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "* \u8981\u83b7\u5f97\u60f3\u8981\u7684\u7ed3\u679c\uff0c\u60a8\u53ef\u4ee5\u5c06\u5faa\u73af\u53d8\u91cf\u4f5c\u4e3a\u547d\u540d\u53d8\u91cf\u4f20\u9012\u7ed9\u51fd\u6570\u3002 **\u4e3a\u4ec0\u4e48\u4f1a\u8fd9\u6837\uff1f** \u56e0\u4e3a\u8fd9\u4f1a\u5728\u51fd\u6570\u7684\u4f5c\u7528\u57df\u5185\u5b9a\u4e49\u53d8\u91cf\u3002 \u5b83\u5c06\u4e0d\u518d\u8fdb\u5165\u5468\u56f4\uff08\u5168\u5c40\uff09\u8303\u56f4\u6765\u67e5\u627e\u53d8\u91cf\u503c\uff0c\u800c\u662f\u4f1a\u521b\u5efa\u4e00\u4e2a\u5c40\u90e8\u53d8\u91cf\u6765\u5b58\u50a8\u8be5\u65f6\u95f4\u70b9\u7684\u201cx\u201d\u503c\u3002\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "funcs = []\n",
+ "for x in range(7):\n",
+ " def some_func(x=x):\n",
+ " return x\n",
+ " funcs.append(some_func)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[0, 1, 2, 3, 4, 5, 6]\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "funcs_results = [func() for func in funcs]\n",
+ "funcs_results\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\u6b64\u65f6\uff0c\u4e0d\u518d\u4f7f\u7528\u5168\u5c40\u53d8\u91cf `x`\uff1a\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "ClosureVars(nonlocals={}, globals={}, builtins={}, unbound=set())\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "inspect.getclosurevars(funcs[0])\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > The chicken-egg problem/\u5148\u6709\u9e21\u8fd8\u662f\u5148\u6709\u86cb *\n",
+ "1\\.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "isinstance(3, int)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "isinstance(type, object)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "isinstance(object, type)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\u90a3\u4e48\u5230\u5e95\u8c01\u662f\u201c\u6700\u7ec8\u201d\u7684\u57fa\u7c7b\u5462\uff1f\u4e0b\u8fb9\u987a\u4fbf\u5217\u51fa\u66f4\u591a\u7684\u4ee4\u4eba\u56f0\u60d1\u7684\u5730\u65b9\n",
+ "\n",
+ "2\\. \n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "False\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "class A: pass\n",
+ "isinstance(A, A)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "isinstance(type, type)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "isinstance(object, object)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "3\\.\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "issubclass(int, object)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "issubclass(type, object)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "False\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "issubclass(object, type)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e\n",
+ "\n",
+ "- `type` \u662f Python \u4e2d\u7684[\u5143\u7c7b](https://realpython.com/python-metaclasses/)\u3002\n",
+ "- Python \u4e2d\uff0c**\u4e00\u5207**\u7686\u5bf9\u8c61\uff0c\u5176\u4e2d\u5305\u62ec\u7c7b\u53ca\u5176\u5bf9\u8c61\uff08\u5b9e\u4f8b\uff09\u3002\n",
+ "- `type` \u7c7b\u578b\u662f`object`\u7c7b\u7684\u5143\u7c7b\uff0c\u6bcf\u4e2a\u7c7b\uff08\u5305\u62ec`type`\uff09\u90fd\u76f4\u63a5\u6216\u95f4\u63a5\u5730\u7ee7\u627f\u81ea`object`\u3002\n",
+ "- \u5bf9\u8c61\u548c\u7c7b\u578b\u4e4b\u95f4\u6ca1\u6709\u771f\u6b63\u7684\u57fa\u7c7b\u3002\u4e0a\u8ff0\u7247\u6bb5\u4e2d\u7684\u4ee4\u4eba\u56f0\u60d1\u7684\u5730\u65b9\u4e4b\u6240\u4ee5\u51fa\u73b0\uff0c\u662f\u56e0\u4e3a\u6211\u4eec\u4ece Python \u7c7b\u7684\u89d2\u5ea6\u8003\u8651\u8fd9\u4e9b\u5173\u7cfb\uff08issubclass \u548c isinstance\uff09\u3002 `object`\u548c`type`\u4e4b\u95f4\u7684\u5173\u7cfb\u4e0d\u80fd\u5728\u7eafpython\u4e2d\u91cd\u73b0\u3002 \u66f4\u51c6\u786e\u5730\u8bf4\uff0c\u4ee5\u4e0b\u5173\u7cfb\u4e0d\u80fd\u5728\u7eaf Python \u4e2d\u91cd\u73b0:\n",
+ " + A\u7c7b\u662fB\u7c7b\u7684\u4e00\u4e2a\u5b9e\u4f8b\uff0cB\u7c7b\u662fA\u7c7b\u7684\u4e00\u4e2a\u5b9e\u4f8b\u3002\n",
+ " + A\u7c7b\u662f\u5b83\u81ea\u5df1\u7684\u4e00\u4e2a\u5b9e\u4f8b\u3002\n",
+ "- `object`\u548c`type`\u4e4b\u95f4\u7684\u5173\u7cfb\uff08\u65e2\u662f\u5f7c\u6b64\u7684\u5b9e\u4f8b\uff0c\u4e5f\u662f\u5b83\u4eec\u81ea\u5df1\u7684\u5b9e\u4f8b\uff09\u5b58\u5728\u4e8e Python \u4e2d\uff0c\u8fd9\u662f\u6e90\u4e8e\u5b9e\u73b0\u5c42\u7ea7\u4e0a\u7684\u201c\u4f5c\u5f0a\u201d\u884c\u4e3a\u3002\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Subclass relationships/\u5b50\u7c7b\u5173\u7cfb *\n",
+ "**Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "from collections import Hashable\n",
+ "issubclass(list, object)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "issubclass(object, Hashable)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "False\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "issubclass(list, Hashable)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\u5b50\u7c7b\u5173\u7cfb\u5e94\u8be5\u662f\u53ef\u4f20\u9012\u7684, \u5bf9\u5427? (\u5373, \u5982\u679c `A` \u662f `B` \u7684\u5b50\u7c7b, `B` \u662f `C` \u7684\u5b50\u7c7b, \u90a3\u4e48 `A` _\u5e94\u8be5_ \u662f `C` \u7684\u5b50\u7c7b.)\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "\n",
+ "* Python \u4e2d\u7684\u5b50\u7c7b\u5173\u7cfb\u5e76\u4e0d\u4e00\u5b9a\u662f\u4f20\u9012\u7684. \u4efb\u4f55\u4eba\u90fd\u53ef\u4ee5\u5728\u5143\u7c7b\u4e2d\u968f\u610f\u5b9a\u4e49 `__subclasscheck__`.\n",
+ "* \u5f53 `issubclass(cls, Hashable)` \u88ab\u8c03\u7528\u65f6, \u5b83\u53ea\u662f\u5728 `cls` \u4e2d\u5bfb\u627e `__hash__` \u65b9\u6cd5\u6216\u8005\u4ece\u7ee7\u627f\u7684\u7236\u7c7b\u4e2d\u5bfb\u627e `__hash__` \u65b9\u6cd5.\n",
+ "* \u7531\u4e8e `object` is \u53ef\u6563\u5217\u7684(hashable), \u4f46\u662f `list` \u662f\u4e0d\u53ef\u6563\u5217\u7684, \u6240\u4ee5\u5b83\u6253\u7834\u4e86\u8fd9\u79cd\u4f20\u9012\u5173\u7cfb.\n",
+ "* \u5728[\u8fd9\u91cc](https://www.naftaliharris.com/blog/python-subclass-intransitivity/)\u53ef\u4ee5\u627e\u5230\u66f4\u8be6\u7ec6\u7684\u89e3\u91ca.\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Methods equality and identity/\u65b9\u6cd5\u7684\u76f8\u7b49\u6027\u548c\u552f\u4e00\u6027 *\n",
+ "1.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "class SomeClass:\n",
+ " def method(self):\n",
+ " pass\n",
+ "\n",
+ " @classmethod\n",
+ " def classm(cls):\n",
+ " pass\n",
+ "\n",
+ " @staticmethod\n",
+ " def staticm():\n",
+ " pass\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "collapsed": true
+ },
+ "execution_count": null,
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "True\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(SomeClass.method is SomeClass.method)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "collapsed": true
+ },
+ "execution_count": null,
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "False\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(SomeClass.classm is SomeClass.classm)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "collapsed": true
+ },
+ "execution_count": null,
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "True\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(SomeClass.classm == SomeClass.classm)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "collapsed": true
+ },
+ "execution_count": null,
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "True\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(SomeClass.staticm is SomeClass.staticm)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\u8bbf\u95ee `classm` \u4e24\u6b21\uff0c\u6211\u4eec\u5f97\u5230\u4e00\u4e2a\u76f8\u7b49\u7684\u5bf9\u8c61\uff0c\u4f46\u4e0d\u662f*\u540c\u4e00\u4e2a*\uff1f \u8ba9\u6211\u4eec\u770b\u770b `SomeClass` \u7684\u5b9e\u4f8b\u4f1a\u53d1\u751f\u4ec0\u4e48\uff1a\n",
+ "\n",
+ "2.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "o1 = SomeClass()\n",
+ "o2 = SomeClass()\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "collapsed": true
+ },
+ "execution_count": null,
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "False\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(o1.method == o2.method)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "collapsed": true
+ },
+ "execution_count": null,
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "True\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(o1.method == o1.method)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "collapsed": true
+ },
+ "execution_count": null,
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "False\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(o1.method is o1.method)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "collapsed": true
+ },
+ "execution_count": null,
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "False\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(o1.classm is o1.classm)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "collapsed": true
+ },
+ "execution_count": null,
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "True\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(o1.classm == o1.classm == o2.classm == SomeClass.classm)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "collapsed": true
+ },
+ "execution_count": null,
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "True\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(o1.staticm is o1.staticm is o2.staticm is SomeClass.staticm)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\u8bbf\u95ee ` classm` or `method` \u4e24\u6b21, \u4e3a `SomeClass` \u7684\u540c\u4e00\u4e2a\u5b9e\u4f8b\u521b\u5efa\u4e86\u76f8\u7b49\u4f46\u662f*\u4e0d\u540c*\u7684\u5bf9\u8c61\u3002\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e\n",
+ "* \u51fd\u6570\u662f[\u63cf\u8ff0\u7b26](https://docs.python.org/3/howto/descriptor.html)\u3002\u6bcf\u5f53\u5c06\u51fd\u6570\u4f5c\u4e3a\u5c5e\u6027\u8bbf\u95ee\u65f6\uff0c\u5c31\u4f1a\u8c03\u7528\u63cf\u8ff0\u7b26\uff0c\u521b\u5efa\u4e00\u4e2a\u65b9\u6cd5\u5bf9\u8c61\uff0c\u8be5\u5bf9\u8c61\u5c06\u51fd\u6570\u4e0e\u62e5\u6709\u8be5\u5c5e\u6027\u7684\u5bf9\u8c61\u201c\u7ed1\u5b9a\u201d\u3002\u5982\u679c\u88ab\u8c03\u7528\uff0c\u8be5\u65b9\u6cd5\u8c03\u7528\u51fd\u6570\uff0c\u9690\u5f0f\u4f20\u9012\u7ed1\u5b9a\u5bf9\u8c61\u4f5c\u4e3a\u7b2c\u4e00\u4e2a\u53c2\u6570\uff08\u8fd9\u5c31\u662f\u6211\u4eec\u5982\u4f55\u5c06 self \u4f5c\u4e3a\u7b2c\u4e00\u4e2a\u53c2\u6570\u83b7\u53d6\uff0c\u5c3d\u7ba1\u6ca1\u6709\u663e\u5f0f\u4f20\u9012\u5b83\uff09\u3002\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ ">\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "o1.method\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "* \u591a\u6b21\u8bbf\u95ee\u8be5\u5c5e\u6027\uff0c\u6bcf\u6b21\u90fd\u4f1a\u521b\u5efa\u4e00\u4e2a\u65b9\u6cd5\u5bf9\u8c61\uff01 \u56e0\u6b64\uff0c`o1.method is o1.method` \u6c38\u8fdc\u4e0d\u4f1a\u662f\u771f\u7684\u3002\u4f46\u662f\uff0c\u5c06\u51fd\u6570\u4f5c\u4e3a\u7c7b\u5c5e\u6027\uff08\u800c\u4e0d\u662f\u5b9e\u4f8b\uff09\u8bbf\u95ee\u5e76\u4e0d\u4f1a\u521b\u5efa\u65b9\u6cd5\u5bf9\u8c61\uff0c\u6240\u4ee5 `SomeClass.method is SomeClass.method` \u662f\u771f\u7684\u3002\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "SomeClass.method\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "* `classmethod` \u5c06\u51fd\u6570\u8f6c\u6362\u4e3a\u7c7b\u65b9\u6cd5\u3002 \u7c7b\u65b9\u6cd5\u662f\u63cf\u8ff0\u7b26\uff0c\u5f53\u88ab\u8bbf\u95ee\u65f6\uff0c\u5b83\u4f1a\u521b\u5efa\u4e00\u4e2a\u7ed1\u5b9a*\u7c7b\u672c\u8eab*\u7684\u65b9\u6cd5\u5bf9\u8c61\uff0c\u800c\u4e0d\u662f\u5bf9\u8c61\u672c\u8eab\u3002\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ ">\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "o1.classm\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "* \u4e0e\u51fd\u6570\u4e0d\u540c\uff0c`classmethod` \u5728\u4f5c\u4e3a\u7c7b\u5c5e\u6027\u8bbf\u95ee\u65f6\u4e5f\u4f1a\u521b\u5efa\u4e00\u4e2a\u65b9\u6cd5\uff08\u5728\u8fd9\u79cd\u60c5\u51b5\u4e0b\uff0c\u5b83\u4eec\u7ed1\u5b9a\u7c7b\uff0c\u800c\u4e0d\u662f\u7c7b\u7684\u7c7b\u578b\uff09\u3002 \u6240\u4ee5 `SomeClass.classm is SomeClass.classm` \u662f\u5047\u7684\u3002\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ ">\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "SomeClass.classm\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "* \u5f53\u4e24\u4e2a\u51fd\u6570\u76f8\u7b49\u5e76\u4e14\u7ed1\u5b9a\u7684\u5bf9\u8c61\u76f8\u540c\u65f6\uff0c\u65b9\u6cd5\u5bf9\u8c61\u6bd4\u8f83\u76f8\u7b49\u3002 \u6240\u4ee5`o1.method == o1.method` \u4e3a\u771f\uff0c\u5c3d\u7ba1\u5b83\u4eec\u5728\u5185\u5b58\u4e2d\u662f\u4e24\u4e2a\u4e0d\u540c\u7684\u5bf9\u8c61\u3002\n",
+ "* `staticmethod` \u5c06\u51fd\u6570\u8f6c\u6362\u4e3a\u201c\u65e0\u64cd\u4f5c\u201d\u63cf\u8ff0\u7b26\uff0c\u5b83\u6309\u539f\u6837\u8fd4\u56de\u51fd\u6570\u3002\u6ca1\u6709\u65b9\u6cd5\u5bf9\u8c61\u88ab\u521b\u5efa\uff0c\u6240\u4ee5 `is` \u7684\u6bd4\u8f83\u8fd0\u7b97\u4e3a\u771f\u3002\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "o1.staticm\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "SomeClass.staticm\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "* \u6bcf\u6b21 Python \u8c03\u7528\u5b9e\u4f8b\u65b9\u6cd5\u65f6\u90fd\u5fc5\u987b\u521b\u5efa\u65b0\u7684\u201c\u65b9\u6cd5\u201d\u5bf9\u8c61\uff0c\u5e76\u4e14\u6bcf\u6b21\u90fd\u5fc5\u987b\u4fee\u6539\u53c2\u6570\u4ee5\u63d2\u5165 `self` \u4e25\u91cd\u5f71\u54cd\u6027\u80fd\u3002CPython 3.7 [\u89e3\u51b3\u4e86\u8fd9\u4e2a\u95ee\u9898](https://bugs.python.org/issue26110) \u3002\u901a\u8fc7\u5f15\u5165\u65b0\u7684\u64cd\u4f5c\u7801\u6765\u5904\u7406\u8c03\u7528\u65b9\u6cd5\u800c\u4e0d\u521b\u5efa\u4e34\u65f6\u65b9\u6cd5\u5bf9\u8c61\u3002\u8fd9\u4ec5\u5728\u5b9e\u9645\u8c03\u7528\u8bbf\u95ee\u7684\u51fd\u6570\u65f6\u4f7f\u7528\uff0c\u56e0\u6b64\u8fd9\u91cc\u7684\u4ee3\u7801\u7247\u6bb5\u4e0d\u53d7\u5f71\u54cd\uff0c\u4ecd\u7136\u4f1a\u751f\u6210\u65b9\u6cd5:)\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > All-true-ation/\u8fd4\u56deTrue\u7684all\u51fd\u6570 *\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "all([True, True, True])\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "False\n",
+ "\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "all([True, True, False])\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "all([])\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "False\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "all([[]])\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "all([[[]]])\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\u4e3a\u4ec0\u4e48\u4f1a\u6709\u8fd9\u79cdTrue-False\u7684\u53d8\u5316\uff1f\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e\n",
+ "\n",
+ "- `all` \u51fd\u6570\u7684\u5b9e\u73b0\u7b49\u4ef7\u4e8e\uff1a\n",
+ "\n",
+ "- ```py\n",
+ " def all(iterable):\n",
+ " for element in iterable:\n",
+ " if not element:\n",
+ " return False\n",
+ " return True\n",
+ " ```\n",
+ "\n",
+ "- `all([])` \u8fd4\u56de `True` \u56e0\u4e3a\u53ef\u8fed\u4ee3\u5bf9\u8c61\u4e3a\u7a7a\u3002 \n",
+ "- `all([[]])` \u8fd4\u56de `False` \u56e0\u4e3a\u4f20\u5165\u7684\u6570\u7ec4\u6709\u4e00\u4e2a\u5143\u7d20 `[]`\uff0c \u5728Python\u4e2d\uff0c\u7a7a\u5217\u8868\u4e3a\u5047\u3002\n",
+ "- `all([[[]]])` \u548c\u66f4\u9ad8\u7684\u9012\u5f52\u53d8\u4f53\u603b\u662f`True`\u3002 \u8fd9\u662f\u56e0\u4e3a\u4f20\u9012\u7684\u6570\u7ec4\u7684\u5355\u4e2a\u5143\u7d20\uff08`[[...]]`\uff09\u4e0d\u518d\u662f\u7a7a\u7684\uff0c\u800c\u6709\u503c\u7684\u5217\u8868\u4e3a\u771f\u3002\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > The surprising comma/\u610f\u5916\u7684\u9017\u53f7\n",
+ "**Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " File \"\", line 1\n",
+ " def h(x, **kwargs,):\n",
+ " ^\n",
+ "SyntaxError: invalid syntax\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "def f(x, y,):\n",
+ " print(x, y)\n",
+ "\n",
+ "def g(x=4, y=5,):\n",
+ " print(x, y)\n",
+ "\n",
+ "def h(x, **kwargs,):\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " File \"\", line 1\n",
+ " def h(*args,):\n",
+ " ^\n",
+ "SyntaxError: invalid syntax\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "def h(*args,):\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "\n",
+ "- \u5728Python\u51fd\u6570\u7684\u5f62\u5f0f\u53c2\u6570\u5217\u8868\u4e2d, \u5c3e\u968f\u9017\u53f7\u5e76\u4e0d\u4e00\u5b9a\u662f\u5408\u6cd5\u7684.\n",
+ "- \u5728Python\u4e2d, \u53c2\u6570\u5217\u8868\u90e8\u5206\u7528\u524d\u7f6e\u9017\u53f7\u5b9a\u4e49, \u90e8\u5206\u7528\u5c3e\u968f\u9017\u53f7\u5b9a\u4e49. \u8fd9\u79cd\u51b2\u7a81\u5bfc\u81f4\u9017\u53f7\u88ab\u5939\u5728\u4e2d\u95f4, \u6ca1\u6709\u89c4\u5219\u5b9a\u4e49\u5b83.(\u8bd1:\u8fd9\u4e00\u53e5\u770b\u5f97\u6211\u4e5f\u5f88\u61f5\u903c,\u53ea\u80fd\u5f3a\u7ffb\u4e86.\u8be6\u7ec6\u89e3\u91ca\u770b\u4e0b\u9762\u7684\u8ba8\u8bba\u5e16\u4f1a\u4e00\u76ee\u4e86\u7136.)\n",
+ "- **\u6ce8\u610f:** \u5c3e\u968f\u9017\u53f7\u7684\u95ee\u9898\u5df2\u7ecf\u5728Python 3.6\u4e2d\u88ab[\u4fee\u590d](https://bugs.python.org/issue9232)\u4e86. \u800c\u8fd9\u7bc7[\u5e16\u5b50](https://bugs.python.org/issue9232#msg248399)\u4e2d\u5219\u7b80\u8981\u8ba8\u8bba\u4e86Python\u4e2d\u5c3e\u968f\u9017\u53f7\u7684\u4e0d\u540c\u7528\u6cd5.\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Strings and the backslashes/\u5b57\u7b26\u4e32\u4e0e\u53cd\u659c\u6760\n",
+ "**Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "collapsed": true
+ },
+ "execution_count": null,
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\"\n",
+ "\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(\"\\\"\")\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "collapsed": true
+ },
+ "execution_count": null,
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\\\"\n",
+ "\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(r\"\\\"\")\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "collapsed": true
+ },
+ "execution_count": null,
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "File \"\", line 1\n",
+ " print(r\"\\\")\n",
+ " ^\n",
+ "SyntaxError: EOL while scanning string literal\n",
+ "\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(r\"\\\")\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "r'\\'' == \"\\\\'\"\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "\n",
+ "- \u5728\u4e00\u822c\u7684python\u5b57\u7b26\u4e32\u4e2d\uff0c\u53cd\u659c\u6760\u7528\u4e8e\u8f6c\u4e49\u53ef\u80fd\u5177\u6709\u7279\u6b8a\u542b\u4e49\u7684\u5b57\u7b26\uff08\u5982\u5355\u5f15\u53f7\u3001\u53cc\u5f15\u53f7\u548c\u53cd\u659c\u6760\u672c\u8eab\uff09\u3002\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " 'wt\"f'\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " \"wt\\\"f\"\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "- \u5728\u4ee5 `r` \u5f00\u5934\u7684\u539f\u59cb\u5b57\u7b26\u4e32\u4e2d, \u53cd\u659c\u6760\u5e76\u6ca1\u6709\u7279\u6b8a\u542b\u4e49.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " r'wt\\\"f' == 'wt\\\\\"f'\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " 'wt\\\\\"f'\n",
+ "\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " print(repr(r'wt\\\"f')\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " print(\"\\n\")\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " '\\\\n'\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " print(r\"\\\\n\")\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "- \u8fd9\u610f\u5473\u7740\u5f53\u89e3\u6790\u5668\u5728\u539f\u59cb\u5b57\u7b26\u4e32\u4e2d\u9047\u5230\u53cd\u659c\u6760\u65f6\uff0c\u5b83\u671f\u671b\u540e\u9762\u6709\u53e6\u4e00\u4e2a\u5b57\u7b26\u3002 \u5728\u6211\u4eec\u7684\u4f8b\u5b50\u4e2d\uff08`print(r\"\\\")`\uff09\uff0c\u53cd\u659c\u6760\u8f6c\u4e49\u4e86\u5c3e\u968f\u5f15\u53f7\uff0c\u4f7f\u89e3\u6790\u5668\u6ca1\u6709\u7ec8\u6b62\u5f15\u53f7\uff08\u56e0\u6b64\u4ea7\u751f\u4e86`SyntaxError`\uff09\u3002 \u8fd9\u5c31\u662f\u4e3a\u4ec0\u4e48\u53cd\u659c\u6760\u5728\u539f\u59cb\u5b57\u7b26\u4e32\u672b\u5c3e\u4e0d\u8d77\u4f5c\u7528\u7684\u539f\u56e0\u3002\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > not knot!/\u522b\u7ea0\u7ed3!\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "x = True\n",
+ "y = False\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "not x == y\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " File \"\", line 1\n",
+ " x == not y\n",
+ " ^\n",
+ "SyntaxError: invalid syntax\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "x == not y\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "\n",
+ "* \u8fd0\u7b97\u7b26\u7684\u4f18\u5148\u7ea7\u4f1a\u5f71\u54cd\u8868\u8fbe\u5f0f\u7684\u6c42\u503c\u987a\u5e8f, \u800c\u5728 Python \u4e2d `==` \u8fd0\u7b97\u7b26\u7684\u4f18\u5148\u7ea7\u8981\u9ad8\u4e8e `not` \u8fd0\u7b97\u7b26.\n",
+ "* \u6240\u4ee5 `not x == y` \u76f8\u5f53\u4e8e `not (x == y)`, \u540c\u65f6\u7b49\u4ef7\u4e8e `not (True == False)`, \u6700\u540e\u7684\u8fd0\u7b97\u7ed3\u679c\u5c31\u662f `True`.\n",
+ "* \u4e4b\u6240\u4ee5 `x == not y` \u4f1a\u629b\u4e00\u4e2a `SyntaxError` \u5f02\u5e38, \u662f\u56e0\u4e3a\u5b83\u4f1a\u88ab\u8ba4\u4e3a\u7b49\u4ef7\u4e8e `(x == not) y`, \u800c\u4e0d\u662f\u4f60\u4e00\u5f00\u59cb\u671f\u671b\u7684 `x == (not y)`.\n",
+ "* \u89e3\u91ca\u5668\u671f\u671b `not` \u6807\u8bb0\u662f `not in` \u64cd\u4f5c\u7b26\u7684\u4e00\u90e8\u5206 (\u56e0\u4e3a `==` \u548c `not in` \u64cd\u4f5c\u7b26\u5177\u6709\u76f8\u540c\u7684\u4f18\u5148\u7ea7), \u4f46\u662f\u5b83\u5728 `not` \u6807\u8bb0\u540e\u9762\u627e\u4e0d\u5230 `in` \u6807\u8bb0, \u6240\u4ee5\u4f1a\u629b\u51fa `SyntaxError` \u5f02\u5e38.\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Half triple-quoted strings/\u4e09\u4e2a\u5f15\u53f7\n",
+ "**Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "collapsed": true
+ },
+ "execution_count": null,
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "wtfpython\n"
+ ]
+ }
+ ],
+ "source": [
+ "print('wtfpython''')\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "collapsed": true
+ },
+ "execution_count": null,
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "wtfpython\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(\"wtfpython\"\"\")\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "# \u4e0b\u9762\u7684\u8bed\u53e5\u4f1a\u629b\u51fa `SyntaxError` \u5f02\u5e38\n",
+ "# print('''wtfpython')\n",
+ "# print(\"\"\"wtfpython\")\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "+ Python \u63d0\u4f9b\u9690\u5f0f\u7684[\u5b57\u7b26\u4e32\u8fde\u63a5](https://docs.python.org/2/reference/lexical_analysis.html#string-literal-concatenation), \u4f8b\u5982,\n",
+ " ```\n",
+ " >>> print(\"wtf\" \"python\")\n",
+ " wtfpython\n",
+ " >>> print(\"wtf\" \"\") # or \"wtf\"\"\"\n",
+ " wtf\n",
+ " ```\n",
+ "+ `'''` \u548c `\"\"\"` \u5728 Python\u4e2d\u4e5f\u662f\u5b57\u7b26\u4e32\u5b9a\u754c\u7b26, Python \u89e3\u91ca\u5668\u5728\u5148\u9047\u5230\u4e09\u4e2a\u5f15\u53f7\u7684\u7684\u65f6\u5019\u4f1a\u5c1d\u8bd5\u518d\u5bfb\u627e\u4e09\u4e2a\u7ec8\u6b62\u5f15\u53f7\u4f5c\u4e3a\u5b9a\u754c\u7b26, \u5982\u679c\u4e0d\u5b58\u5728\u5219\u4f1a\u5bfc\u81f4 `SyntaxError` \u5f02\u5e38.\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > What's wrong with booleans?/\u5e03\u5c14\u4f60\u548b\u4e86?\n",
+ "1\\.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "# \u4e00\u4e2a\u7b80\u5355\u7684\u4f8b\u5b50, \u7edf\u8ba1\u4e0b\u9762\u53ef\u8fed\u4ee3\u5bf9\u8c61\u4e2d\u7684\u5e03\u5c14\u578b\u503c\u7684\u4e2a\u6570\u548c\u6574\u578b\u503c\u7684\u4e2a\u6570\n",
+ "mixed_list = [False, 1.0, \"some_string\", 3, True, [], False]\n",
+ "integers_found_so_far = 0\n",
+ "booleans_found_so_far = 0\n",
+ "\n",
+ "for item in mixed_list:\n",
+ " if isinstance(item, int):\n",
+ " integers_found_so_far += 1\n",
+ " elif isinstance(item, bool):\n",
+ " booleans_found_so_far += 1\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "4\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "integers_found_so_far\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "0\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "booleans_found_so_far\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "2\\.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "'wtf'\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "some_bool = True\n",
+ "\"wtf\" * some_bool\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "''\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "some_bool = False\n",
+ "\"wtf\" * some_bool\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "3\\.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "def tell_truth():\n",
+ " True = False\n",
+ " if True == False:\n",
+ " print(\"I have lost faith in truth!\")\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output (< 3.x):**\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "I have lost faith in truth!\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "tell_truth()\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "\n",
+ "* \u5e03\u5c14\u503c\u662f `int` \u7684\u5b50\u7c7b\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " issubclass(bool, int)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " False\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " issubclass(int, bool)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "* \u56e0\u6b64\uff0c`True` \u548c `False` \u662f `int` \u7684\u5b9e\u4f8b\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " isinstance(True, int)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " isinstance(False, int)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "* `True` \u7684\u6574\u6570\u503c\u662f `1`, \u800c `False` \u7684\u6574\u6570\u503c\u662f `0`\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " 1\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " int(True)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " 0\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " int(False)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "* \u5173\u4e8e\u5176\u80cc\u540e\u7684\u539f\u7406, \u8bf7\u770b\u8fd9\u4e2a StackOverflow \u7684[\u56de\u7b54](https://stackoverflow.com/a/8169049/4354153).\n",
+ "\n",
+ "* \u6700\u521d\uff0cPython \u6ca1\u6709 `bool` \u7c7b\u578b\uff08\u4eba\u4eec\u4f7f\u7528 0 \u8868\u793a\u5047\uff0c\u4f7f\u7528\u975e\u96f6\u503c\uff0c\u5982 1 \u8868\u793a\u771f\uff09\u3002`True`\u3001`False` \u548c `bool` \u7c7b\u578b\u5728 2.x \u7248\u672c\u4e2d\u88ab\u6dfb\u52a0\uff0c\u4f46\u4e3a\u4e86\u5411\u540e\u517c\u5bb9\uff0c`True` \u548c `False` \u4e0d\u80fd\u6210\u4e3a\u5e38\u91cf\u3002\u5b83\u4eec\u53ea\u662f\u5185\u7f6e\u53d8\u91cf\uff0c\u53ef\u4ee5\u91cd\u65b0\u5206\u914d\u5b83\u4eec\n",
+ "\n",
+ "* Python 3 \u5411\u540e\u4e0d\u517c\u5bb9\uff0c\u95ee\u9898\u7ec8\u4e8e\u5f97\u5230\u89e3\u51b3\uff0c\u56e0\u6b64\u6700\u540e\u4e00\u4e2a\u4ee3\u7801\u6bb5\u4e0d\u9002\u7528\u4e8e Python 3.x\uff01\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Class attributes and instance attributes/\u7c7b\u5c5e\u6027\u548c\u5b9e\u4f8b\u5c5e\u6027\n",
+ "1\\.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "class A:\n",
+ " x = 1\n",
+ "\n",
+ "class B(A):\n",
+ " pass\n",
+ "\n",
+ "class C(A):\n",
+ " pass\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "(1, 1, 1)\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "A.x, B.x, C.x\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "(1, 2, 1)\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "B.x = 2\n",
+ "A.x, B.x, C.x\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "(3, 2, 3)\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "A.x = 3\n",
+ "A.x, B.x, C.x\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "(3, 3)\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "a = A()\n",
+ "a.x, A.x\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "(4, 3)\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "a.x += 1\n",
+ "a.x, A.x\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "2\\.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "class SomeClass:\n",
+ " some_var = 15\n",
+ " some_list = [5]\n",
+ " another_list = [5]\n",
+ " def __init__(self, x):\n",
+ " self.some_var = x + 1\n",
+ " self.some_list = self.some_list + [x]\n",
+ " self.another_list += [x]\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[5, 420]\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "some_obj = SomeClass(420)\n",
+ "some_obj.some_list\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[5, 420]\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "some_obj.another_list\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[5, 111]\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "another_obj = SomeClass(111)\n",
+ "another_obj.some_list\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[5, 420, 111]\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "another_obj.another_list\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "another_obj.another_list is SomeClass.another_list\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "another_obj.another_list is some_obj.another_list\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "\n",
+ "* \u7c7b\u53d8\u91cf\u548c\u5b9e\u4f8b\u53d8\u91cf\u5728\u5185\u90e8\u662f\u901a\u8fc7\u7c7b\u5bf9\u8c61\u7684\u5b57\u5178\u6765\u5904\u7406(\u8bd1: \u5c31\u662f `__dict__` \u5c5e\u6027). \u5982\u679c\u5728\u5f53\u524d\u7c7b\u7684\u5b57\u5178\u4e2d\u627e\u4e0d\u5230\u7684\u8bdd\u5c31\u53bb\u5b83\u7684\u7236\u7c7b\u4e2d\u5bfb\u627e.\n",
+ "* `+=` \u8fd0\u7b97\u7b26\u4f1a\u5728\u539f\u5730\u4fee\u6539\u53ef\u53d8\u5bf9\u8c61, \u800c\u4e0d\u662f\u521b\u5efa\u65b0\u5bf9\u8c61. \u56e0\u6b64, \u5728\u8fd9\u79cd\u60c5\u51b5\u4e0b, \u4fee\u6539\u4e00\u4e2a\u5b9e\u4f8b\u7684\u5c5e\u6027\u4f1a\u5f71\u54cd\u5176\u4ed6\u5b9e\u4f8b\u548c\u7c7b\u5c5e\u6027.\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > yielding None/\u751f\u6210 None\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "some_iterable = ('a', 'b')\n",
+ "\n",
+ "def some_func(val):\n",
+ " return \"something\"\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "['a', 'b']\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "[x for x in some_iterable]\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " at 0x7f70b0a4ad58>\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "[(yield x) for x in some_iterable]\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "['a', 'b']\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "list([(yield x) for x in some_iterable])\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "['a', None, 'b', None]\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "list((yield x) for x in some_iterable)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "['a', 'something', 'b', 'something']\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "list(some_func((yield x)) for x in some_iterable)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "- \u6765\u6e90\u548c\u89e3\u91ca\u53ef\u4ee5\u5728\u8fd9\u91cc\u627e\u5230: https://stackoverflow.com/questions/32139885/yield-in-list-comprehensions-and-generator-expressions\n",
+ "- \u76f8\u5173\u9519\u8bef\u62a5\u544a: http://bugs.python.org/issue10544\n",
+ "- \u8fd9\u4e2abug\u57283.7\u4ee5\u540e\u7684\u7248\u672c\u4e2d\u4e0d\u88ab\u63a8\u8350\u4f7f\u7528, \u5e76\u57283.8\u4e2d\u88ab\u4fee\u590d. \u56e0\u6b64\u57283.8\u4e2d\u5c1d\u8bd5\u5728\u63a8\u5bfc\u5f0f\u4e2d\u4f7f\u7528 yield, \u53ea\u4f1a\u5f97\u5230\u4e00\u4e2a SyntaxError. \u8be6\u7ec6\u5185\u5bb9\u53ef\u4ee5\u770b[3.7\u66f4\u65b0\u5185\u5bb9](https://docs.python.org/dev/whatsnew/3.7.html#deprecated-python-behavior), [3.8\u66f4\u65b0\u5185\u5bb9](https://docs.python.org/dev/whatsnew/3.8.html#changes-in-python-behavior).\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Yielding from... return!/\u751f\u6210\u5668\u91cc\u7684return *\n",
+ "1\\.\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "def some_func(x):\n",
+ " if x == 3:\n",
+ " return [\"wtf\"]\n",
+ " else:\n",
+ " yield from range(x)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output (> 3.3):**\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[]\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "list(some_func(3))\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "`\"wtf\"` \u53bb\u54ea\u513f\u4e86\uff1f\u662f\u56e0\u4e3a`yield from`\u7684\u4e00\u4e9b\u7279\u6b8a\u6548\u679c\u5417\uff1f\u8ba9\u6211\u4eec\u9a8c\u8bc1\u4e00\u4e0b\n",
+ "\n",
+ "2\\.\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "def some_func(x):\n",
+ " if x == 3:\n",
+ " return [\"wtf\"]\n",
+ " else:\n",
+ " for i in range(x):\n",
+ " yield i\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[]\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "list(some_func(3))\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\u540c\u6837\u7684\u7ed3\u679c\uff0c\u8fd9\u91cc\u4e5f\u4e0d\u8d77\u4f5c\u7528\u3002\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e\n",
+ "\n",
+ "+ \u4ece Python 3.3 \u5f00\u59cb\uff0c\u53ef\u4ee5\u5728\u751f\u6210\u5668\u4e2d\u4f7f\u7528\u5e26\u6709\u503c\u7684 `return` \u8bed\u53e5\uff08\u53c2\u89c1 [PEP380](https://www.python.org/dev/peps/pep-0380/)\uff09\u3002 [\u5b98\u65b9\u6587\u6863](https://www.python.org/dev/peps/pep-0380/#enhancements-to-stopiteration) \u63cf\u8ff0\uff0c\n",
+ "\n",
+ "> \"... \u751f\u6210\u5668\u4e2d\u7684 `return expr` \u4f1a\u5bfc\u81f4\u5728\u9000\u51fa\u751f\u6210\u5668\u65f6\u5f15\u53d1 `StopIteration(expr)`\u3002\"\n",
+ "\n",
+ "+ \u5728 `some_func(3)` \u4f8b\u5b50\u4e2d\uff0c`return` \u8bed\u53e5\u5728\u5f00\u59cb\u5c31\u5f15\u53d1\u4e86`StopIteration`\u3002 `StopIteration` \u5f02\u5e38\u4f1a\u5728`list(...)` \u5305\u88c5\u5668\u548c`for` \u5faa\u73af\u4e2d\u81ea\u52a8\u6355\u83b7\u3002 \u56e0\u6b64\uff0c\u4ee5\u4e0a\u4e24\u4e2a\u7247\u6bb5\u90fd\u4ea7\u751f\u7684\u662f\u4e00\u4e2a\u7a7a\u5217\u8868\u3002\n",
+ "\n",
+ "+ \u8981\u4ece\u751f\u6210\u5668 `some_func` \u4e2d\u83b7\u53d6 `[\"wtf\"]`\uff0c\u6211\u4eec\u9700\u8981\u6355\u83b7 `StopIteration` \u5f02\u5e38\uff0c\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " try:\n",
+ " next(some_func(3))\n",
+ " except StopIteration as e:\n",
+ " some_string = e.value\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " [\"wtf\"]\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " some_string\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Nan-reflexivity/Nan\u7684\u81ea\u53cd\u6027\n",
+ "1\\.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "a = float('inf')\n",
+ "b = float('nan')\n",
+ "c = float('-iNf') # \u8fd9\u4e9b\u5b57\u7b26\u4e32\u4e0d\u533a\u5206\u5927\u5c0f\u5199\n",
+ "d = float('nan')\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "inf\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "a\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "nan\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "b\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "-inf\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "c\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "ValueError: could not convert string to float: some_other_string\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "float('some_other_string')\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "a == -c #inf==inf\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "None == None # None==None\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "False\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "b == d #\u4f46\u662f nan!=nan\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "0.0\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "50/a\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "nan\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "a/a\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "nan\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "23 + b\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "2\\.\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "x = float('nan')\n",
+ "y = x / x\n",
+ "y is y # \u540c\u4e00\u6027(identity)\u5177\u5907\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "False\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "y == y # y\u4e0d\u5177\u5907\u76f8\u7b49\u6027(equality)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "[y] == [y] # \u4f46\u5305\u542by\u7684\u5217\u8868\u9a8c\u8bc1\u76f8\u7b49\u6027(equality)\u6210\u529f\u4e86\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "\n",
+ "`'inf'` \u548c `'nan'` \u662f\u7279\u6b8a\u7684\u5b57\u7b26\u4e32(\u4e0d\u533a\u5206\u5927\u5c0f\u5199), \u5f53\u663e\u793a\u8f6c\u6362\u6210 `float` \u578b\u65f6, \u5b83\u4eec\u5206\u522b\u7528\u4e8e\u8868\u793a\u6570\u5b66\u610f\u4e49\u4e0a\u7684 \"\u65e0\u7a77\u5927\" \u548c \"\u975e\u6570\u5b57\".\n",
+ "- \u7531\u4e8e\u6839\u636e IEEE \u6807\u51c6 `NaN != NaN`\uff0c\u9075\u5b88\u6b64\u89c4\u5219\u6253\u7834\u4e86 Python \u4e2d\u96c6\u5408\u5143\u7d20\u7684\u81ea\u53cd\u6027\u5047\u8bbe\uff0c\u5373\u5982\u679c `x` \u662f `list` \u7b49\u96c6\u5408\u7684\u4e00\u90e8\u5206\uff0c\u5219\u6bd4\u8f83\u7b49\u8fd0\u7b97\u7684\u5b9e\u73b0\u57fa\u4e8e\u5047\u8bbe`x == x`\u3002\u7531\u4e8e\u8fd9\u4e2a\u5047\u8bbe\uff0c\u5728\u6bd4\u8f83\u4e24\u4e2a\u5143\u7d20\u65f6\u9996\u5148\u6bd4\u8f83\u8eab\u4efd`identity`\uff08\u56e0\u4e3a\u5b83\u66f4\u5feb\uff09\uff0c\u5e76\u4e14\u4ec5\u5728\u8eab\u4efd\u4e0d\u5339\u914d\u65f6\u624d\u6bd4\u8f83\u503c\u3002\u4ee5\u4e0b\u7247\u6bb5\u5c06\u66f4\u6e05\u695a\u5730\u8bf4\u660e\uff0c\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " (False, True)\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " x = float('nan')\n",
+ " x == x, [x] == [x]\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " (False, True)\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " y = float('nan')\n",
+ " y == y, [y] == [y]\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " (False, False)\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " x == y, [x] == [y]\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ " \u7531\u4e8e `x` \u548c `y` \u7684\u8eab\u4efd`identity`\u4e0d\u540c\uff0c\u6240\u4ee5\u8003\u8651\u7684\u503c\u4e5f\u4e0d\u540c\uff1b \u56e0\u6b64\u8fd9\u6b21\u6bd4\u8f83\u8fd4\u56de\u201cFalse\u201d\u3002\n",
+ "\n",
+ "\n",
+ "- \u611f\u5174\u8da3\u53ef\u4ee5\u9605\u8bfb [Reflexivity, and other pillars of civilization](https://bertrandmeyer.com/2010/02/06/reflexivity-and-other-pillars-of-civilization/)\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Mutating the immutable!/\u5f3a\u4eba\u6240\u96be\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "some_tuple = (\"A\", \"tuple\", \"with\", \"values\")\n",
+ "another_tuple = ([1, 2], [3, 4], [5, 6])\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "TypeError: 'tuple' object does not support item assignment\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "some_tuple[2] = \"change this\"\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "([1, 2], [3, 4], [5, 6, 1000])\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "another_tuple[2].append(1000) # \u8fd9\u91cc\u4e0d\u51fa\u73b0\u9519\u8bef\n",
+ "another_tuple\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "TypeError: 'tuple' object does not support item assignment\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "another_tuple[2] += [99, 999]\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "([1, 2], [3, 4], [5, 6, 1000, 99, 999])\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "another_tuple\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\u6211\u8fd8\u4ee5\u4e3a\u5143\u7ec4\u662f\u4e0d\u53ef\u53d8\u7684\u5462...\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "\n",
+ "* \u5f15\u7528 https://docs.python.org/2/reference/datamodel.html\n",
+ "\n",
+ " > \u4e0d\u53ef\u53d8\u5e8f\u5217\n",
+ " \u4e0d\u53ef\u53d8\u5e8f\u5217\u7684\u5bf9\u8c61\u4e00\u65e6\u521b\u5efa\u5c31\u4e0d\u80fd\u518d\u6539\u53d8. (\u5982\u679c\u5bf9\u8c61\u5305\u542b\u5bf9\u5176\u4ed6\u5bf9\u8c61\u7684\u5f15\u7528\uff0c\u5219\u8fd9\u4e9b\u5176\u4ed6\u5bf9\u8c61\u53ef\u80fd\u662f\u53ef\u53d8\u7684\u5e76\u4e14\u53ef\u80fd\u4f1a\u88ab\u4fee\u6539; \u4f46\u662f\uff0c\u7531\u4e0d\u53ef\u53d8\u5bf9\u8c61\u76f4\u63a5\u5f15\u7528\u7684\u5bf9\u8c61\u96c6\u5408\u4e0d\u80fd\u66f4\u6539.)\n",
+ "\n",
+ "* `+=` \u64cd\u4f5c\u7b26\u5728\u539f\u5730\u4fee\u6539\u4e86\u5217\u8868. \u5143\u7d20\u8d4b\u503c\u64cd\u4f5c\u5e76\u4e0d\u5de5\u4f5c, \u4f46\u662f\u5f53\u5f02\u5e38\u629b\u51fa\u65f6, \u5143\u7d20\u5df2\u7ecf\u5728\u539f\u5730\u88ab\u4fee\u6539\u4e86.\n",
+ "\n",
+ "(\u8bd1: \u5bf9\u4e8e\u4e0d\u53ef\u53d8\u5bf9\u8c61, \u8fd9\u91cc\u6307tuple, `+=` \u5e76\u4e0d\u662f\u539f\u5b50\u64cd\u4f5c, \u800c\u662f `extend` \u548c `=` \u4e24\u4e2a\u52a8\u4f5c, \u8fd9\u91cc `=` \u64cd\u4f5c\u867d\u7136\u4f1a\u629b\u51fa\u5f02\u5e38, \u4f46 `extend` \u64cd\u4f5c\u5df2\u7ecf\u4fee\u6539\u6210\u529f\u4e86. \u8be6\u7ec6\u89e3\u91ca\u53ef\u4ee5\u770b[\u8fd9\u91cc](https://segmentfault.com/a/1190000010767068))\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > The disappearing variable from outer scope/\u6d88\u5931\u7684\u5916\u90e8\u53d8\u91cf\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "e = 7\n",
+ "try:\n",
+ " raise Exception()\n",
+ "except Exception as e:\n",
+ " pass\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output (Python 2.x):**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "collapsed": true
+ },
+ "execution_count": null,
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "# prints nothing\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(e)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output (Python 3.x):**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "collapsed": true
+ },
+ "execution_count": null,
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "NameError: name 'e' is not defined\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(e)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "\n",
+ "* \u51fa\u5904: https://docs.python.org/3/reference/compound_stmts.html#except\n",
+ "\n",
+ " \u5f53\u4f7f\u7528 `as` \u4e3a\u76ee\u6807\u5206\u914d\u5f02\u5e38\u7684\u65f6\u5019, \u5c06\u5728except\u5b50\u53e5\u7684\u672b\u5c3e\u6e05\u9664\u8be5\u5f02\u5e38.\n",
+ "\n",
+ " \u8fd9\u5c31\u597d\u50cf\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " except E as N:\n",
+ " foo\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ " \u4f1a\u88ab\u7ffb\u8bd1\u6210\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " except E as N:\n",
+ " try:\n",
+ " foo\n",
+ " finally:\n",
+ " del N\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ " \u8fd9\u610f\u5473\u7740\u5f02\u5e38\u5fc5\u987b\u5728\u88ab\u8d4b\u503c\u7ed9\u5176\u4ed6\u53d8\u91cf\u624d\u80fd\u5728 `except` \u5b50\u53e5\u4e4b\u540e\u5f15\u7528\u5b83. \u800c\u5f02\u5e38\u4e4b\u6240\u4ee5\u4f1a\u88ab\u6e05\u9664, \u5219\u662f\u7531\u4e8e\u4e0a\u9762\u9644\u52a0\u7684\u56de\u6eaf\u4fe1\u606f(trackback)\u4f1a\u548c\u6808\u5e27(stack frame)\u5f62\u6210\u5faa\u73af\u5f15\u7528, \u4f7f\u5f97\u8be5\u6808\u5e27\u4e2d\u7684\u6240\u6709\u672c\u5730\u53d8\u91cf\u5728\u4e0b\u4e00\u6b21\u5783\u573e\u56de\u6536\u53d1\u751f\u4e4b\u524d\u90fd\u5904\u4e8e\u6d3b\u52a8\u72b6\u6001.(\u8bd1: \u4e5f\u5c31\u662f\u8bf4\u4e0d\u4f1a\u88ab\u56de\u6536)\n",
+ "\n",
+ "* \u5b50\u53e5\u5728 Python \u4e2d\u5e76\u6ca1\u6709\u72ec\u7acb\u7684\u4f5c\u7528\u57df. \u793a\u4f8b\u4e2d\u7684\u6240\u6709\u5185\u5bb9\u90fd\u5904\u4e8e\u540c\u4e00\u4f5c\u7528\u57df\u5185, \u6240\u4ee5\u53d8\u91cf `e` \u4f1a\u7531\u4e8e\u6267\u884c\u4e86 `except` \u5b50\u53e5\u800c\u88ab\u5220\u9664. \u800c\u5bf9\u4e8e\u6709\u72ec\u7acb\u7684\u5185\u90e8\u4f5c\u7528\u57df\u7684\u51fd\u6570\u6765\u8bf4\u60c5\u51b5\u5c31\u4e0d\u4e00\u6837\u4e86. \u4e0b\u9762\u7684\u4f8b\u5b50\u8bf4\u660e\u4e86\u8fd9\u4e00\u70b9:\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " def f(x):\n",
+ " del(x)\n",
+ " print(x)\n",
+ "\n",
+ " x = 5\n",
+ " y = [5, 4, 3]\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ " **Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " 5\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " >>>f(x)\n",
+ " UnboundLocalError: local variable 'x' referenced before assignment\n",
+ " >>>f(y)\n",
+ " UnboundLocalError: local variable 'x' referenced before assignment\n",
+ " x\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " [5, 4, 3]\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " y\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "* \u5728 Python 2.x \u4e2d, `Exception()` \u5b9e\u4f8b\u88ab\u8d4b\u503c\u7ed9\u4e86\u53d8\u91cf `e`, \u6240\u4ee5\u5f53\u4f60\u5c1d\u8bd5\u6253\u5370\u7ed3\u679c\u7684\u65f6\u5019, \u5b83\u7684\u8f93\u51fa\u4e3a\u7a7a.\uff08\u8bd1: \u6b63\u5e38\u7684Exception\u5b9e\u4f8b\u6253\u5370\u51fa\u6765\u5c31\u662f\u7a7a\uff09\n",
+ "\n",
+ " **Output (Python 2.x):**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " Exception()\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " e\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " # \u6ca1\u6709\u6253\u5370\u4efb\u4f55\u5185\u5bb9!\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " print e\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > The mysterious key type conversion/\u795e\u79d8\u7684\u952e\u578b\u8f6c\u6362 *\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "class SomeClass(str):\n",
+ " pass\n",
+ "\n",
+ "some_dict = {'s':42}\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "str\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "type(list(some_dict.keys())[0])\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{'s': 40}\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "s = SomeClass('s')\n",
+ "some_dict[s] = 40\n",
+ "some_dict # \u9884\u671f: \u4e24\u4e2a\u4e0d\u540c\u7684\u952e\u503c\u5bf9\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "str\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "type(list(some_dict.keys())[0])\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "\n",
+ "* \u7531\u4e8e `SomeClass` \u4f1a\u4ece `str` \u81ea\u52a8\u7ee7\u627f `__hash__` \u65b9\u6cd5, \u6240\u4ee5 `s` \u5bf9\u8c61\u548c `\"s\"` \u5b57\u7b26\u4e32\u7684\u54c8\u5e0c\u503c\u662f\u76f8\u540c\u7684.\n",
+ "* \u800c `SomeClass(\"s\") == \"s\"` \u4e3a `True` \u662f\u56e0\u4e3a `SomeClass` \u4e5f\u7ee7\u627f\u4e86 `str` \u7c7b `__eq__` \u65b9\u6cd5.\n",
+ "* \u7531\u4e8e\u4e24\u8005\u7684\u54c8\u5e0c\u503c\u76f8\u540c\u4e14\u76f8\u7b49, \u6240\u4ee5\u5b83\u4eec\u5728\u5b57\u5178\u4e2d\u8868\u793a\u76f8\u540c\u7684\u952e.\n",
+ "* \u5982\u679c\u60f3\u8981\u5b9e\u73b0\u671f\u671b\u7684\u529f\u80fd, \u6211\u4eec\u53ef\u4ee5\u91cd\u5b9a\u4e49 `SomeClass` \u7684 `__eq__` \u65b9\u6cd5.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " class SomeClass(str):\n",
+ " def __eq__(self, other):\n",
+ " return (\n",
+ " type(self) is SomeClass\n",
+ " and type(other) is SomeClass\n",
+ " and super().__eq__(other)\n",
+ " )\n",
+ "\n",
+ " # \u5f53\u6211\u4eec\u81ea\u5b9a\u4e49 __eq__ \u65b9\u6cd5\u65f6, Python \u4e0d\u4f1a\u518d\u81ea\u52a8\u7ee7\u627f __hash__ \u65b9\u6cd5\n",
+ " # \u6240\u4ee5\u6211\u4eec\u4e5f\u9700\u8981\u5b9a\u4e49\u5b83\n",
+ " __hash__ = str.__hash__\n",
+ "\n",
+ " some_dict = {'s':42}\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ " **Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " {'s': 40, 's': 42}\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " s = SomeClass('s')\n",
+ " some_dict[s] = 40\n",
+ " some_dict\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " (__main__.SomeClass, str)\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " keys = list(some_dict.keys())\n",
+ " type(keys[0]), type(keys[1])\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Let's see if you can guess this?/\u770b\u770b\u4f60\u80fd\u5426\u731c\u5230\u8fd9\u4e00\u70b9?\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "a, b = a[b] = {}, 5\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{5: ({...}, 5)}\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "a\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "\n",
+ "* \u6839\u636e [Python \u8bed\u8a00\u53c2\u8003](https://docs.python.org/2/reference/simple_stmts.html#assignment-statements), \u8d4b\u503c\u8bed\u53e5\u7684\u5f62\u5f0f\u5982\u4e0b\n",
+ " ```\n",
+ " (target_list \"=\")+ (expression_list | yield_expression)\n",
+ " ```\n",
+ "\n",
+ " > \u8d4b\u503c\u8bed\u53e5\u8ba1\u7b97\u8868\u8fbe\u5f0f\u5217\u8868(expression list)(\u7262\u8bb0 \u8fd9\u53ef\u4ee5\u662f\u5355\u4e2a\u8868\u8fbe\u5f0f\u6216\u4ee5\u9017\u53f7\u5206\u9694\u7684\u5217\u8868, \u540e\u8005\u8fd4\u56de\u5143\u7ec4)\u5e76\u5c06\u5355\u4e2a\u7ed3\u679c\u5bf9\u8c61\u4ece\u5de6\u5230\u53f3\u5206\u914d\u7ed9\u76ee\u6807\u5217\u8868\u4e2d\u7684\u6bcf\u4e00\u9879.\n",
+ "\n",
+ "* `(target_list \"=\")+` \u4e2d\u7684 `+` \u610f\u5473\u7740\u53ef\u4ee5\u6709**\u4e00\u4e2a\u6216\u591a\u4e2a**\u76ee\u6807\u5217\u8868. \u5728\u8fd9\u4e2a\u4f8b\u5b50\u4e2d, \u76ee\u6807\u5217\u8868\u662f `a, b` \u548c `a[b]` (\u6ce8\u610f\u8868\u8fbe\u5f0f\u5217\u8868\u53ea\u80fd\u6709\u4e00\u4e2a, \u5728\u6211\u4eec\u7684\u4f8b\u5b50\u4e2d\u662f `{}, 5`).\n",
+ "\n",
+ "* \u8868\u8fbe\u5f0f\u5217\u8868\u8ba1\u7b97\u7ed3\u675f\u540e, \u5c06\u5176\u503c\u81ea\u52a8\u89e3\u5305\u540e**\u4ece\u5de6\u5230\u53f3**\u5206\u914d\u7ed9\u76ee\u6807\u5217\u8868(target list). \u56e0\u6b64, \u5728\u6211\u4eec\u7684\u4f8b\u5b50\u4e2d, \u9996\u5148\u5c06 `{}, 5` \u5143\u7ec4\u5e76\u8d4b\u503c\u7ed9 `a, b`, \u7136\u540e\u6211\u4eec\u5c31\u53ef\u4ee5\u5f97\u5230 `a = {}` \u4e14 `b = 5`.\n",
+ "\n",
+ "* `a` \u88ab\u8d4b\u503c\u7684 `{}` \u662f\u53ef\u53d8\u5bf9\u8c61.\n",
+ "\n",
+ "* \u7b2c\u4e8c\u4e2a\u76ee\u6807\u5217\u8868\u662f `a[b]` (\u4f60\u53ef\u80fd\u89c9\u5f97\u8fd9\u91cc\u4f1a\u62a5\u9519, \u56e0\u4e3a\u5728\u4e4b\u524d\u7684\u8bed\u53e5\u4e2d `a` \u548c `b` \u90fd\u8fd8\u6ca1\u6709\u88ab\u5b9a\u4e49. \u4f46\u662f\u522b\u5fd8\u4e86, \u6211\u4eec\u521a\u521a\u5c06 `a` \u8d4b\u503c `{}` \u4e14\u5c06 `b` \u8d4b\u503c\u4e3a `5`).\n",
+ "\n",
+ "* \u73b0\u5728, \u6211\u4eec\u5c06\u901a\u8fc7\u5c06\u5b57\u5178\u4e2d\u952e `5` \u7684\u503c\u8bbe\u7f6e\u4e3a\u5143\u7ec4 `({}, 5)` \u6765\u521b\u5efa\u5faa\u73af\u5f15\u7528 (\u8f93\u51fa\u4e2d\u7684 `{...}` \u6307\u4e0e `a` \u5f15\u7528\u4e86\u76f8\u540c\u7684\u5bf9\u8c61). \u4e0b\u9762\u662f\u4e00\u4e2a\u66f4\u7b80\u5355\u7684\u5faa\u73af\u5f15\u7528\u7684\u4f8b\u5b50\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " [[...]]\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " some_list = some_list[0] = [0]\n",
+ " some_list\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " [[...]]\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " some_list[0]\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " some_list is some_list[0]\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " some_list[0][0][0][0][0][0] == some_list\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ " \u6211\u4eec\u7684\u4f8b\u5b50\u5c31\u662f\u8fd9\u79cd\u60c5\u51b5 (`a[b][0]` \u4e0e `a` \u662f\u76f8\u540c\u7684\u5bf9\u8c61)\n",
+ "\n",
+ "* \u603b\u7ed3\u4e00\u4e0b, \u4f60\u4e5f\u53ef\u4ee5\u628a\u4f8b\u5b50\u62c6\u6210\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " a, b = {}, 5\n",
+ " a[b] = a, b\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ " \u5e76\u4e14\u53ef\u4ee5\u901a\u8fc7 `a[b][0]` \u4e0e `a` \u662f\u76f8\u540c\u7684\u5bf9\u8c61\u6765\u8bc1\u660e\u662f\u5faa\u73af\u5f15\u7528\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " a[b][0] is a\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Exceeds the limit for integer string conversion/\u6574\u578b\u8f6c\u5b57\u7b26\u4e32\u8d8a\u754c\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "# Python 3.10.6\n",
+ "int(\"2\" * 5432)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "# Python 3.10.8\n",
+ "int(\"2\" * 5432)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "222222222222222222222222222222222222222222222222222222222222222...\n",
+ "\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "# Python 3.10.6\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "Traceback (most recent call last):\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "# Python 3.10.8\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "ValueError: Exceeds the limit (4300) for integer string conversion:\n",
+ " value has 5432 digits; use sys.set_int_max_str_digits()\n",
+ " to increase the limit.\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " \n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "\n",
+ "* \u5bf9`int()`\u7684\u8c03\u7528\u5728Python 3.10.6\u4e2d\u8fd0\u884c\u826f\u597d\uff0c\u4f46\u5728Python 3.10.8\u4e2d\u5f15\u53d1ValueError\u3002\u8bf7\u6ce8\u610f\uff0cPython\u4ecd\u7136\u53ef\u4ee5\u5904\u7406\u5927\u6574\u6570\u3002\u53ea\u6709\u5728\u6574\u578b\u548c\u5b57\u7b26\u4e32\u4e4b\u95f4\u8f6c\u6362\u65f6\u624d\u4f1a\u51fa\u73b0\u6b64\u9519\u8bef\u3002\n",
+ "* \u5e78\u8fd0\u7684\u662f\uff0c\u5f53\u60a8\u5e0c\u671b\u64cd\u4f5c\u8d85\u8fc7\u5141\u8bb8\u7684\u4f4d\u6570\u9650\u5236\u65f6\uff0c\u53ef\u4ee5\u589e\u52a0\u8be5\u9650\u5236\u7684\u4e0a\u9650\u3002\u4e3a\u6b64\uff0c\u53ef\u4ee5\u4f7f\u7528\u4ee5\u4e0b\u65b9\u6cd5\u4e4b\u4e00\uff1a\n",
+ " - \u4f7f\u7528 -X int_max_str_digits \u7684\u547d\u4ee4\u884c\u53c2\u6570\uff08\u4f8b\u5982\uff0c python3 -X int_max_str_digits=640\uff09\n",
+ " - \u4f7f\u7528\u6765\u81easys\u6a21\u5757\u7684set_int_max_str_digits()\u51fd\u6570\n",
+ " - \u8bbe\u5b9a PYTHONINTMAXSTRDIGITS \u73af\u5883\u53d8\u91cf\n",
+ "\n",
+ "\u66f4\u591a\u66f4\u6539\u8bbe\u7f6e\u4e0a\u9650\u7684\u64cd\u4f5c\u7ec6\u8282\u67e5\u770b[\u6587\u6863](https://docs.python.org/3/library/stdtypes.html#int-max-str-digits)\u3002\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Modifying a dictionary while iterating over it/\u8fed\u4ee3\u5b57\u5178\u65f6\u7684\u4fee\u6539\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "x = {0: None}\n",
+ "\n",
+ "for i in x:\n",
+ " del x[i]\n",
+ " x[i+1] = None\n",
+ " print(i)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output (Python 2.7- Python 3.5):**\n",
+ "\n",
+ "```\n",
+ "0\n",
+ "1\n",
+ "2\n",
+ "3\n",
+ "4\n",
+ "5\n",
+ "6\n",
+ "7\n",
+ "```\n",
+ "\n",
+ "\u662f\u7684, \u5b83\u8fd0\u884c\u4e86**\u516b\u6b21**\u7136\u540e\u624d\u505c\u4e0b\u6765.\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "\n",
+ "* Python\u4e0d\u652f\u6301\u5bf9\u5b57\u5178\u8fdb\u884c\u8fed\u4ee3\u7684\u540c\u65f6\u4fee\u6539\u5b83.\n",
+ "* \u5b83\u4e4b\u6240\u4ee5\u8fd0\u884c8\u6b21, \u662f\u56e0\u4e3a\u5b57\u5178\u4f1a\u81ea\u52a8\u6269\u5bb9\u4ee5\u5bb9\u7eb3\u66f4\u591a\u952e\u503c(\u6211\u4eec\u67098\u6b21\u5220\u9664\u8bb0\u5f55, \u56e0\u6b64\u9700\u8981\u6269\u5bb9). \u8fd9\u5b9e\u9645\u4e0a\u662f\u4e00\u4e2a\u5b9e\u73b0\u7ec6\u8282. (\u8bd1: \u5e94\u8be5\u662f\u56e0\u4e3a\u5b57\u5178\u7684\u521d\u59cb\u6700\u5c0f\u503c\u662f8, \u6269\u5bb9\u4f1a\u5bfc\u81f4\u6563\u5217\u8868\u5730\u5740\u53d1\u751f\u53d8\u5316\u800c\u4e2d\u65ad\u5faa\u73af.)\n",
+ "* \u5728\u4e0d\u540c\u7684Python\u5b9e\u73b0\u4e2d\u5220\u9664\u952e\u7684\u5904\u7406\u65b9\u5f0f\u4ee5\u53ca\u8c03\u6574\u5927\u5c0f\u7684\u65f6\u95f4\u53ef\u80fd\u4f1a\u6709\u6240\u4e0d\u540c.(\u8bd1: \u5c31\u662f\u8bf4\u4ec0\u4e48\u65f6\u5019\u6269\u5bb9\u5728\u4e0d\u540c\u7248\u672c\u4e2d\u53ef\u80fd\u662f\u4e0d\u540c\u7684, \u57283.6\u53ca3.7\u7684\u7248\u672c\u4e2d\u5230[5](https://github.com/python/cpython/blob/v3.6.1/Objects/dictobject.c#L103-L110)\u5c31\u4f1a\u81ea\u52a8\u6269\u5bb9\u4e86. \u4ee5\u540e\u4e5f\u6709\u53ef\u80fd\u518d\u6b21\u53d1\u751f\u53d8\u5316. \u8fd9\u662f\u4e3a\u4e86\u907f\u514d\u6563\u5217\u51b2\u7a81. \u987a\u5e26\u4e00\u63d0, \u540e\u9762\u4e24\u6b21\u6269\u5bb9\u4f1a\u6269\u5c55\u4e3a32\u548c256. \u5373`8->32->256`.)\n",
+ "* \u66f4\u591a\u7684\u4fe1\u606f, \u4f60\u53ef\u4ee5\u53c2\u8003\u8fd9\u4e2aStackOverflow\u7684[\u56de\u7b54](https://stackoverflow.com/questions/44763802/bug-in-python-dict), \u5b83\u8be6\u7ec6\u7684\u89e3\u91ca\u4e00\u4e2a\u7c7b\u4f3c\u7684\u4f8b\u5b50.\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Stubborn `del` operator/\u575a\u5f3a\u7684 `del` *\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "class SomeClass:\n",
+ " def __del__(self):\n",
+ " print(\"Deleted!\")\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n",
+ "1\\.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "Deleted!\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "x = SomeClass()\n",
+ "y = x\n",
+ "del x # \u8fd9\u91cc\u5e94\u8be5\u4f1a\u8f93\u51fa \"Deleted!\"\n",
+ "del y\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\u5537, \u7ec8\u4e8e\u5220\u9664\u4e86. \u4f60\u53ef\u80fd\u5df2\u7ecf\u731c\u5230\u4e86\u5728\u6211\u4eec\u7b2c\u4e00\u6b21\u5c1d\u8bd5\u5220\u9664 `x` \u65f6\u662f\u4ec0\u4e48\u8ba9 `__del__` \u514d\u4e8e\u88ab\u8c03\u7528\u7684. \u90a3\u8ba9\u6211\u4eec\u7ed9\u8fd9\u4e2a\u4f8b\u5b50\u589e\u52a0\u70b9\u96be\u5ea6.\n",
+ "\n",
+ "2\\.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "<__main__.SomeClass instance at 0x7f98a1a67fc8>\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "x = SomeClass()\n",
+ "y = x\n",
+ "del x\n",
+ "y # \u68c0\u67e5\u4e00\u4e0by\u662f\u5426\u5b58\u5728\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "Deleted!\n",
+ "{'__builtins__': , 'SomeClass': , '__package__': None, '__name__': '__main__', '__doc__': None}\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "del y # \u50cf\u4e4b\u524d\u4e00\u6837, \u8fd9\u91cc\u5e94\u8be5\u4f1a\u8f93\u51fa \"Deleted!\"\n",
+ "globals() # \u597d\u5427, \u5e76\u6ca1\u6709. \u8ba9\u6211\u4eec\u770b\u4e00\u4e0b\u6240\u6709\u7684\u5168\u5c40\u53d8\u91cf\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\u597d\u4e86\uff0c\u73b0\u5728\u5b83\u88ab\u5220\u9664\u4e86 :confused:\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "+ `del x` \u5e76\u4e0d\u4f1a\u7acb\u523b\u8c03\u7528 `x.__del__()`.\n",
+ "+ \u6bcf\u5f53\u9047\u5230 `del x`, Python \u4f1a\u5c06 `x` \u7684\u5f15\u7528\u6570\u51cf1, \u5f53 `x` \u7684\u5f15\u7528\u6570\u51cf\u52300\u65f6\u5c31\u4f1a\u8c03\u7528 `x.__del__()`.\n",
+ "+ \u5728\u7b2c\u4e8c\u4e2a\u4f8b\u5b50\u4e2d, `y.__del__()` \u4e4b\u6240\u4ee5\u672a\u88ab\u8c03\u7528, \u662f\u56e0\u4e3a\u524d\u4e00\u6761\u8bed\u53e5 (`>>> y`) \u5bf9\u540c\u4e00\u5bf9\u8c61\u521b\u5efa\u4e86\u53e6\u4e00\u4e2a\u5f15\u7528, \u4ece\u800c\u9632\u6b62\u5728\u6267\u884c `del y` \u540e\u5bf9\u8c61\u7684\u5f15\u7528\u6570\u53d8\u4e3a0.\n",
+ "+ \u8c03\u7528 `globals` \u5bfc\u81f4\u5f15\u7528\u88ab\u9500\u6bc1, \u56e0\u6b64\u6211\u4eec\u53ef\u4ee5\u770b\u5230 \"Deleted!\" \u7ec8\u4e8e\u88ab\u8f93\u51fa\u4e86.\n",
+ "+ (\u8bd1: \u8fd9\u5176\u5b9e\u662f Python \u4ea4\u4e92\u89e3\u91ca\u5668\u7684\u7279\u6027, \u5b83\u4f1a\u81ea\u52a8\u8ba9 `_` \u4fdd\u5b58\u4e0a\u4e00\u4e2a\u8868\u8fbe\u5f0f\u8f93\u51fa\u7684\u503c, \u8be6\u7ec6\u53ef\u4ee5\u770b[\u8fd9\u91cc](https://www.cnblogs.com/leisurelylicht/p/diao-pi-de-kong-zhi-tai.html).)\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > The out of scope variable/\u5916\u90e8\u4f5c\u7528\u57df\u53d8\u91cf\n",
+ "1\\.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "a = 1\n",
+ "def some_func():\n",
+ " return a\n",
+ "\n",
+ "def another_func():\n",
+ " a += 1\n",
+ " return a\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "2\\.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "def some_closure_func():\n",
+ " a = 1\n",
+ " def some_inner_func():\n",
+ " return a\n",
+ " return some_inner_func()\n",
+ "\n",
+ "def another_closure_func():\n",
+ " a = 1\n",
+ " def another_inner_func():\n",
+ " a += 1\n",
+ " return a\n",
+ " return another_inner_func()\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "1\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "some_func()\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "UnboundLocalError: local variable 'a' referenced before assignment\n",
+ "\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "another_func()\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "1\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "some_closure_func()\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "UnboundLocalError: local variable 'a' referenced before assignment\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "another_closure_func()\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "* \u5f53\u4f60\u5728\u4f5c\u7528\u57df\u4e2d\u5bf9\u53d8\u91cf\u8fdb\u884c\u8d4b\u503c\u65f6, \u53d8\u91cf\u4f1a\u53d8\u6210\u8be5\u4f5c\u7528\u57df\u5185\u7684\u5c40\u90e8\u53d8\u91cf. \u56e0\u6b64 `a` \u4f1a\u53d8\u6210 `another_func` \u51fd\u6570\u4f5c\u7528\u57df\u4e2d\u7684\u5c40\u90e8\u53d8\u91cf, \u4f46\u5b83\u5728\u51fd\u6570\u4f5c\u7528\u57df\u4e2d\u5e76\u6ca1\u6709\u88ab\u521d\u59cb\u5316, \u6240\u4ee5\u4f1a\u5f15\u53d1\u9519\u8bef.\n",
+ "* \u60f3\u8981\u5728 `another_func` \u4e2d\u4fee\u6539\u5916\u90e8\u4f5c\u7528\u57df\u53d8\u91cf `a` \u7684\u8bdd, \u53ef\u4ee5\u4f7f\u7528 `global` \u5173\u952e\u5b57.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " def another_func()\n",
+ " global a\n",
+ " a += 1\n",
+ " return a\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ " **Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " 2\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " another_func()\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "* \u5728 `another_closure_func` \u51fd\u6570\u4e2d\uff0c`a` \u4f1a\u53d8\u6210 `another_inner_func` \u51fd\u6570\u4f5c\u7528\u57df\u4e2d\u7684\u5c40\u90e8\u53d8\u91cf, \u4f46\u5b83\u5728\u540c\u4e00\u4f5c\u7528\u57df\u4e2d\u5e76\u6ca1\u6709\u88ab\u521d\u59cb\u5316, \u6240\u4ee5\u4f1a\u5f15\u53d1\u9519\u8bef\u3002\n",
+ "* \u60f3\u8981\u5728 `another_inner_func` \u4e2d\u4fee\u6539\u5916\u90e8\u4f5c\u7528\u57df\u53d8\u91cf `a` \u7684\u8bdd, \u53ef\u4ee5\u4f7f\u7528 `nonlocal` \u5173\u952e\u5b57\u3002nonlocal \u8868\u8fbe\u5f0f\u7528\u4e8e\uff08\u9664\u5168\u5c40\u4f5c\u7528\u57df\u5916\uff09\u6700\u8fd1\u4e00\u7ea7\u7684\u5916\u90e8\u4f5c\u7528\u57df\u3002\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " def another_func():\n",
+ " a = 1\n",
+ " def another_inner_func():\n",
+ " nonlocal a\n",
+ " a += 1\n",
+ " return a\n",
+ " return another_inner_func()\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ " **Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " 2\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " another_func()\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "* `global` and `nonlocal` \u5173\u952e\u5b57\u544a\u8bc9 `Python` \u89e3\u91ca\u5668\uff0c\u4e0d\u8981\u58f0\u660e\u65b0\u53d8\u91cf\uff0c\u800c\u662f\u5728\u76f8\u5e94\u7684\u5916\u90e8\u4f5c\u7528\u57df\u4e2d\u67e5\u627e\u53d8\u91cf\u3002\n",
+ "* \u53ef\u4ee5\u9605\u8bfb[\u8fd9\u4e2a](https://sebastianraschka.com/Articles/2014_python_scope_and_namespaces.html)\u7b80\u77ed\u5374\u5f88\u68d2\u7684\u6307\u5357, \u4e86\u89e3\u66f4\u591a\u5173\u4e8e Python \u4e2d\u547d\u540d\u7a7a\u95f4\u548c\u4f5c\u7528\u57df\u7684\u5de5\u4f5c\u539f\u7406\u3002\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Deleting a list item while iterating/\u8fed\u4ee3\u5217\u8868\u65f6\u5220\u9664\u5143\u7d20\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "list_1 = [1, 2, 3, 4]\n",
+ "list_2 = [1, 2, 3, 4]\n",
+ "list_3 = [1, 2, 3, 4]\n",
+ "list_4 = [1, 2, 3, 4]\n",
+ "\n",
+ "for idx, item in enumerate(list_1):\n",
+ " del item\n",
+ "\n",
+ "for idx, item in enumerate(list_2):\n",
+ " list_2.remove(item)\n",
+ "\n",
+ "for idx, item in enumerate(list_3[:]):\n",
+ " list_3.remove(item)\n",
+ "\n",
+ "for idx, item in enumerate(list_4):\n",
+ " list_4.pop(idx)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[1, 2, 3, 4]\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "list_1\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[2, 4]\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "list_2\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[]\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "list_3\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[2, 4]\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "list_4\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\u4f60\u80fd\u731c\u5230\u4e3a\u4ec0\u4e48\u8f93\u51fa\u662f `[2, 4]` \u5417?\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "\n",
+ "* \u5728\u8fed\u4ee3\u65f6\u4fee\u6539\u5bf9\u8c61\u662f\u4e00\u4e2a\u5f88\u611a\u8822\u7684\u4e3b\u610f. \u6b63\u786e\u7684\u505a\u6cd5\u662f\u8fed\u4ee3\u5bf9\u8c61\u7684\u526f\u672c, `list_3[:]` \u5c31\u662f\u8fd9\u4e48\u505a\u7684.\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " 139798789457608\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " some_list = [1, 2, 3, 4]\n",
+ " id(some_list)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " 139798779601192\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " id(some_list[:]) # \u6ce8\u610fpython\u4e3a\u5207\u7247\u5217\u8868\u521b\u5efa\u4e86\u65b0\u5bf9\u8c61.\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**`del`, `remove` \u548c `pop` \u7684\u4e0d\u540c:**\n",
+ "* `del var_name` \u53ea\u662f\u4ece\u672c\u5730\u6216\u5168\u5c40\u547d\u540d\u7a7a\u95f4\u4e2d\u5220\u9664\u4e86 `var_name` (\u8fd9\u5c31\u662f\u4e3a\u4ec0\u4e48 `list_1` \u6ca1\u6709\u53d7\u5230\u5f71\u54cd).\n",
+ "* `remove` \u4f1a\u5220\u9664\u7b2c\u4e00\u4e2a\u5339\u914d\u5230\u7684\u6307\u5b9a\u503c, \u800c\u4e0d\u662f\u7279\u5b9a\u7684\u7d22\u5f15, \u5982\u679c\u627e\u4e0d\u5230\u503c\u5219\u629b\u51fa `ValueError` \u5f02\u5e38.\n",
+ "* `pop` \u5219\u4f1a\u5220\u9664\u6307\u5b9a\u7d22\u5f15\u5904\u7684\u5143\u7d20\u5e76\u8fd4\u56de\u5b83, \u5982\u679c\u6307\u5b9a\u4e86\u65e0\u6548\u7684\u7d22\u5f15\u5219\u629b\u51fa `IndexError` \u5f02\u5e38.\n",
+ "\n",
+ "**\u4e3a\u4ec0\u4e48\u8f93\u51fa\u662f `[2, 4]`?**\n",
+ "- \u5217\u8868\u8fed\u4ee3\u662f\u6309\u7d22\u5f15\u8fdb\u884c\u7684, \u6240\u4ee5\u5f53\u6211\u4eec\u4ece `list_2` \u6216 `list_4` \u4e2d\u5220\u9664 `1` \u65f6, \u5217\u8868\u7684\u5185\u5bb9\u5c31\u53d8\u6210\u4e86 `[2, 3, 4]`. \u5269\u4f59\u5143\u7d20\u4f1a\u4f9d\u6b21\u4f4d\u79fb, \u4e5f\u5c31\u662f\u8bf4, `2` \u7684\u7d22\u5f15\u4f1a\u53d8\u4e3a 0, `3` \u4f1a\u53d8\u4e3a 1. \u7531\u4e8e\u4e0b\u4e00\u6b21\u8fed\u4ee3\u5c06\u83b7\u53d6\u7d22\u5f15\u4e3a 1 \u7684\u5143\u7d20 (\u5373 `3`), \u56e0\u6b64 `2` \u5c06\u88ab\u5f7b\u5e95\u7684\u8df3\u8fc7. \u7c7b\u4f3c\u7684\u60c5\u51b5\u4f1a\u4ea4\u66ff\u53d1\u751f\u5728\u5217\u8868\u4e2d\u7684\u6bcf\u4e2a\u5143\u7d20\u4e0a.\n",
+ "\n",
+ "* \u53c2\u8003\u8fd9\u4e2aStackOverflow\u7684[\u56de\u7b54](https://stackoverflow.com/questions/45946228/what-happens-when-you-try-to-delete-a-list-element-while-iterating-over-it)\u6765\u89e3\u91ca\u8fd9\u4e2a\u4f8b\u5b50\n",
+ "* \u5173\u4e8ePython\u4e2d\u5b57\u5178\u7684\u7c7b\u4f3c\u4f8b\u5b50, \u53ef\u4ee5\u53c2\u8003\u8fd9\u4e2aStackoverflow\u7684[\u56de\u7b54](https://stackoverflow.com/questions/45877614/how-to-change-all-the-dictionary-keys-in-a-for-loop-with-d-items).\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Lossy zip of iterators/\u4e22\u4e09\u843d\u56db\u7684zip *\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[0, 1, 2, 3, 4, 5, 6]\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "numbers = list(range(7))\n",
+ "numbers\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "([0, 1, 2], [3, 4, 5, 6])\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "first_three, remaining = numbers[:3], numbers[3:]\n",
+ "first_three, remaining\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[(0, 0), (1, 1), (2, 2)]\n",
+ "# so far so good, let's zip the remaining\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "numbers_iter = iter(numbers)\n",
+ "list(zip(numbers_iter, first_three)) \n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[(4, 3), (5, 4), (6, 5)]\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "list(zip(numbers_iter, remaining))\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "`numbers` \u5217\u8868\u4e2d\u7684\u5143\u7d20 `3` \u54ea\u91cc\u53bb\u4e86\uff1f\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e\n",
+ "\n",
+ "- \u6839\u636ePython [\u6587\u6863](https://docs.python.org/3.3/library/functions.html#zip)\uff0c `zip` \u51fd\u6570\u7684\u5927\u6982\u5b9e\u73b0\u5982\u4e0b\uff1a\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " def zip(*iterables):\n",
+ " sentinel = object()\n",
+ " iterators = [iter(it) for it in iterables]\n",
+ " while iterators:\n",
+ " result = []\n",
+ " for it in iterators:\n",
+ " elem = next(it, sentinel)\n",
+ " if elem is sentinel: return\n",
+ " result.append(elem)\n",
+ " yield tuple(result)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "- \u8be5\u51fd\u6570\u63a5\u53d7\u4efb\u610f\u6570\u91cf\u7684\u53ef\u8fed\u4ee3\u5bf9\u8c61\uff0c\u901a\u8fc7\u8c03\u7528 `next` \u51fd\u6570\u5c06\u5b83\u4eec\u7684\u6bcf\u4e2a\u9879\u76ee\u6dfb\u52a0\u5230 `result` \u5217\u8868\u4e2d\uff0c\u5e76\u5728\u4efb\u4e00\u53ef\u8fed\u4ee3\u5bf9\u8c61\u8017\u5c3d\u65f6\u505c\u6b62\u3002\n",
+ "- \u8fd9\u91cc\u9700\u8981\u6ce8\u610f\u7684\u662f\uff0c\u5f53\u4efb\u4e00\u53ef\u8fed\u4ee3\u5bf9\u8c61\u7528\u5c3d\u65f6\uff0c`result` \u5217\u8868\u4e2d\u7684\u73b0\u6709\u5143\u7d20\u5c06\u88ab\u4e22\u5f03\u3002\u8fd9\u5c31\u662f `numbers_iter` \u4e2d\u7684 `3` \u6240\u53d1\u751f\u7684\u60c5\u51b5\u3002\n",
+ "- \u4f7f\u7528 zip \u6267\u884c\u4e0a\u8ff0\u64cd\u4f5c\u7684\u6b63\u786e\u65b9\u6cd5\u662f:\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " [(0, 0), (1, 1), (2, 2)]\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " numbers = list(range(7))\n",
+ " numbers_iter = iter(numbers)\n",
+ " list(zip(first_three, numbers_iter))\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " [(3, 3), (4, 4), (5, 5), (6, 6)]\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " list(zip(remaining, numbers_iter))\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ " `zip` \u7684\u7b2c\u4e00\u4e2a\u53c2\u6570\u5e94\u5f53\u662f\u6709\u6700\u5c11\u5143\u7d20\u7684\u90a3\u4e2a\u3002\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Loop variables leaking out!/\u5faa\u73af\u53d8\u91cf\u6cc4\u6f0f!\n",
+ "1\\.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "collapsed": true
+ },
+ "execution_count": null,
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": []
+ }
+ ],
+ "source": [
+ "for x in range(7):\n",
+ " if x == 6:\n",
+ " print(x, ': for x inside loop')\n",
+ "print(x, ': x in global')\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "6 : for x inside loop\n",
+ "6 : x in global\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\u4f46\u662f `x` \u4ece\u672a\u5728\u5faa\u73af\u5916\u88ab\u5b9a\u4e49...\n",
+ "\n",
+ "2\\.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "collapsed": true
+ },
+ "execution_count": null,
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": []
+ }
+ ],
+ "source": [
+ "# \u8fd9\u6b21\u6211\u4eec\u5148\u521d\u59cb\u5316x\n",
+ "x = -1\n",
+ "for x in range(7):\n",
+ " if x == 6:\n",
+ " print(x, ': for x inside loop')\n",
+ "print(x, ': x in global')\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "6 : for x inside loop\n",
+ "6 : x in global\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "3\\.\n",
+ "```\n",
+ "x = 1\n",
+ "print([x for x in range(5)])\n",
+ "print(x, ': x in global')\n",
+ "```\n",
+ "\n",
+ "**Output (on Python 2.x):**\n",
+ "```\n",
+ "[0, 1, 2, 3, 4]\n",
+ "(4, ': x in global')\n",
+ "```\n",
+ "\n",
+ "**Output (on Python 3.x):**\n",
+ "```\n",
+ "[0, 1, 2, 3, 4]\n",
+ "1 : x in global\n",
+ "```\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "\n",
+ "- \u5728 Python \u4e2d, for \u5faa\u73af\u4f7f\u7528\u6240\u5728\u4f5c\u7528\u57df\u5e76\u5728\u7ed3\u675f\u540e\u4fdd\u7559\u5b9a\u4e49\u7684\u5faa\u73af\u53d8\u91cf. \u5982\u679c\u6211\u4eec\u66fe\u5728\u5168\u5c40\u547d\u540d\u7a7a\u95f4\u4e2d\u5b9a\u4e49\u8fc7\u5faa\u73af\u53d8\u91cf. \u5728\u8fd9\u79cd\u60c5\u51b5\u4e0b, \u5b83\u4f1a\u91cd\u65b0\u7ed1\u5b9a\u73b0\u6709\u53d8\u91cf.\n",
+ "\n",
+ "- Python 2.x \u548c Python 3.x \u89e3\u91ca\u5668\u5728\u5217\u8868\u63a8\u5bfc\u5f0f\u793a\u4f8b\u4e2d\u7684\u8f93\u51fa\u5dee\u5f02, \u5728\u6587\u6863 [What\u2019s New In Python 3.0](https://docs.python.org/3/whatsnew/3.0.html) \u4e2d\u53ef\u4ee5\u627e\u5230\u76f8\u5173\u7684\u89e3\u91ca:\n",
+ "\n",
+ " > \"\u5217\u8868\u63a8\u5bfc\u4e0d\u518d\u652f\u6301\u53e5\u6cd5\u5f62\u5f0f `[... for var in item1, item2, ...]`. \u53d6\u800c\u4ee3\u4e4b\u7684\u662f `[... for var in (item1, item2, ...)]`. \u53e6\u5916, \u6ce8\u610f\u5217\u8868\u63a8\u5bfc\u5177\u6709\u4e0d\u540c\u7684\u8bed\u4e49: \u5b83\u4eec\u66f4\u63a5\u8fd1\u4e8e `list()` \u6784\u9020\u51fd\u6570\u4e2d\u751f\u6210\u5668\u8868\u8fbe\u5f0f\u7684\u8bed\u6cd5\u7cd6(\u8bd1: \u8fd9\u4e00\u53e5\u6211\u4e5f\u4e0d\u662f\u5f88\u660e\u767d), \u7279\u522b\u662f\u5faa\u73af\u63a7\u5236\u53d8\u91cf\u4e0d\u518d\u6cc4\u6f0f\u5230\u5468\u56f4\u7684\u4f5c\u7528\u57df\u4e2d.\"\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Beware of default mutable arguments!/\u5f53\u5fc3\u9ed8\u8ba4\u7684\u53ef\u53d8\u53c2\u6570!\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "def some_func(default_arg=[]):\n",
+ " default_arg.append(\"some_string\")\n",
+ " return default_arg\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "['some_string']\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "some_func()\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "['some_string', 'some_string']\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "some_func()\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "['some_string']\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "some_func([])\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "['some_string', 'some_string', 'some_string']\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "some_func()\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "\n",
+ "- Python\u4e2d\u51fd\u6570\u7684\u9ed8\u8ba4\u53ef\u53d8\u53c2\u6570\u5e76\u4e0d\u662f\u6bcf\u6b21\u8c03\u7528\u8be5\u51fd\u6570\u65f6\u90fd\u4f1a\u88ab\u521d\u59cb\u5316. \u76f8\u53cd, \u5b83\u4eec\u4f1a\u4f7f\u7528\u6700\u8fd1\u5206\u914d\u7684\u503c\u4f5c\u4e3a\u9ed8\u8ba4\u503c. \u5f53\u6211\u4eec\u660e\u786e\u7684\u5c06 `[]` \u4f5c\u4e3a\u53c2\u6570\u4f20\u9012\u7ed9 `some_func` \u7684\u65f6\u5019, \u5c31\u4e0d\u4f1a\u4f7f\u7528 `default_arg` \u7684\u9ed8\u8ba4\u503c, \u6240\u4ee5\u51fd\u6570\u4f1a\u8fd4\u56de\u6211\u4eec\u6240\u671f\u671b\u7684\u7ed3\u679c.\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " def some_func(default_arg=[]):\n",
+ " default_arg.append(\"some_string\")\n",
+ " return default_arg\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ " **Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " ([],)\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " some_func.__defaults__ # \u8fd9\u91cc\u4f1a\u663e\u793a\u51fd\u6570\u7684\u9ed8\u8ba4\u53c2\u6570\u7684\u503c\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " (['some_string'],)\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " some_func()\n",
+ " some_func.__defaults__\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " (['some_string', 'some_string'],)\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " some_func()\n",
+ " some_func.__defaults__\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " (['some_string', 'some_string'],)\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " some_func([])\n",
+ " some_func.__defaults__\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "- \u907f\u514d\u53ef\u53d8\u53c2\u6570\u5bfc\u81f4\u7684\u9519\u8bef\u7684\u5e38\u89c1\u505a\u6cd5\u662f\u5c06 `None` \u6307\u5b9a\u4e3a\u53c2\u6570\u7684\u9ed8\u8ba4\u503c, \u7136\u540e\u68c0\u67e5\u662f\u5426\u6709\u503c\u4f20\u7ed9\u5bf9\u5e94\u7684\u53c2\u6570. \u4f8b:\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " def some_func(default_arg=None):\n",
+ " if not default_arg:\n",
+ " default_arg = []\n",
+ " default_arg.append(\"some_string\")\n",
+ " return default_arg\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Catching the Exceptions/\u6355\u83b7\u5f02\u5e38\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "some_list = [1, 2, 3]\n",
+ "try:\n",
+ " # \u8fd9\u91cc\u4f1a\u629b\u51fa\u5f02\u5e38 ``IndexError``\n",
+ " print(some_list[4])\n",
+ "except IndexError, ValueError:\n",
+ " print(\"Caught!\")\n",
+ "\n",
+ "try:\n",
+ " # \u8fd9\u91cc\u4f1a\u629b\u51fa\u5f02\u5e38 ``ValueError``\n",
+ " some_list.remove(4)\n",
+ "except IndexError, ValueError:\n",
+ " print(\"Caught again!\")\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output (Python 2.x):**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "Caught!\n",
+ "\n",
+ "ValueError: list.remove(x): x not in list\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output (Python 3.x):**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " File \"\", line 3\n",
+ " except IndexError, ValueError:\n",
+ " ^\n",
+ "SyntaxError: invalid syntax\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "\n",
+ "* \u5982\u679c\u4f60\u60f3\u8981\u540c\u65f6\u6355\u83b7\u591a\u4e2a\u4e0d\u540c\u7c7b\u578b\u7684\u5f02\u5e38\u65f6, \u4f60\u9700\u8981\u5c06\u5b83\u4eec\u7528\u62ec\u53f7\u5305\u6210\u4e00\u4e2a\u5143\u7ec4\u4f5c\u4e3a\u7b2c\u4e00\u4e2a\u53c2\u6570\u4f20\u9012. \u7b2c\u4e8c\u4e2a\u53c2\u6570\u662f\u53ef\u9009\u540d\u79f0, \u5982\u679c\u4f60\u63d0\u4f9b, \u5b83\u5c06\u4e0e\u88ab\u6355\u83b7\u7684\u5f02\u5e38\u5b9e\u4f8b\u7ed1\u5b9a. \u4f8b,\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " some_list = [1, 2, 3]\n",
+ " try:\n",
+ " # \u8fd9\u91cc\u4f1a\u629b\u51fa\u5f02\u5e38 ``ValueError``\n",
+ " some_list.remove(4)\n",
+ " except (IndexError, ValueError), e:\n",
+ " print(\"Caught again!\")\n",
+ " print(e)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ " **Output (Python 2.x):**\n",
+ " ```\n",
+ " Caught again!\n",
+ " list.remove(x): x not in list\n",
+ " ```\n",
+ " **Output (Python 3.x):**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " File \"\", line 4\n",
+ " except (IndexError, ValueError), e:\n",
+ " ^\n",
+ " IndentationError: unindent does not match any outer indentation level\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "* \u5728 Python 3 \u4e2d, \u7528\u9017\u53f7\u533a\u5206\u5f02\u5e38\u4e0e\u53ef\u9009\u540d\u79f0\u662f\u65e0\u6548\u7684; \u6b63\u786e\u7684\u505a\u6cd5\u662f\u4f7f\u7528 `as` \u5173\u952e\u5b57. \u4f8b,\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " some_list = [1, 2, 3]\n",
+ " try:\n",
+ " some_list.remove(4)\n",
+ "\n",
+ " except (IndexError, ValueError) as e:\n",
+ " print(\"Caught again!\")\n",
+ " print(e)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ " **Output:**\n",
+ " ```\n",
+ " Caught again!\n",
+ " list.remove(x): x not in list\n",
+ " ```\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Same operands, different story!/\u540c\u4eba\u4e0d\u540c\u547d!\n",
+ "1\\.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "a = [1, 2, 3, 4]\n",
+ "b = a\n",
+ "a = a + [5, 6, 7, 8]\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[1, 2, 3, 4, 5, 6, 7, 8]\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "a\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[1, 2, 3, 4]\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "b\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "2\\.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "a = [1, 2, 3, 4]\n",
+ "b = a\n",
+ "a += [5, 6, 7, 8]\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[1, 2, 3, 4, 5, 6, 7, 8]\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "a\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[1, 2, 3, 4, 5, 6, 7, 8]\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "b\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "\n",
+ "* `a += b` \u5e76\u4e0d\u603b\u662f\u4e0e `a = a + b` \u8868\u73b0\u76f8\u540c. \u7c7b\u5b9e\u73b0 *`op=`* \u8fd0\u7b97\u7b26\u7684\u65b9\u5f0f *\u4e5f\u8bb8* \u662f\u4e0d\u540c\u7684, \u5217\u8868\u5c31\u662f\u8fd9\u6837\u505a\u7684.\n",
+ "\n",
+ "* \u8868\u8fbe\u5f0f `a = a + [5,6,7,8]` \u4f1a\u751f\u6210\u4e00\u4e2a\u65b0\u5217\u8868, \u5e76\u8ba9 `a` \u5f15\u7528\u8fd9\u4e2a\u65b0\u5217\u8868, \u540c\u65f6\u4fdd\u6301 `b` \u4e0d\u53d8.\n",
+ "\n",
+ "* \u8868\u8fbe\u5f0f `a += [5,6,7,8]` \u5b9e\u9645\u4e0a\u662f\u4f7f\u7528\u7684\u662f \"extend\" \u51fd\u6570, \u6240\u4ee5 `a` \u548c `b` \u4ecd\u7136\u6307\u5411\u5df2\u88ab\u4fee\u6539\u7684\u540c\u4e00\u5217\u8868.\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Name resolution ignoring class scope/\u5ffd\u7565\u7c7b\u4f5c\u7528\u57df\u7684\u540d\u79f0\u89e3\u6790\n",
+ "1\\.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "x = 5\n",
+ "class SomeClass:\n",
+ " x = 17\n",
+ " y = (x for i in range(10))\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "5\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "list(SomeClass.y)[0]\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "2\\.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "x = 5\n",
+ "class SomeClass:\n",
+ " x = 17\n",
+ " y = [x for i in range(10)]\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output (Python 2.x):**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "17\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "SomeClass.y[0]\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output (Python 3.x):**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "5\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "SomeClass.y[0]\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "- \u7c7b\u5b9a\u4e49\u4e2d\u5d4c\u5957\u7684\u4f5c\u7528\u57df\u4f1a\u5ffd\u7565\u7c7b\u5185\u7684\u540d\u79f0\u7ed1\u5b9a.\n",
+ "- \u751f\u6210\u5668\u8868\u8fbe\u5f0f\u6709\u5b83\u81ea\u5df1\u7684\u4f5c\u7528\u57df.\n",
+ "- \u4ece Python 3.X \u5f00\u59cb, \u5217\u8868\u63a8\u5bfc\u5f0f\u4e5f\u6709\u81ea\u5df1\u7684\u4f5c\u7528\u57df.\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Rounding like a banker/\u50cf\u94f6\u884c\u5bb6\u4e00\u6837\u820d\u5165 *\n",
+ "\u8ba9\u6211\u4eec\u5b9e\u73b0\u4e00\u4e2a\u7b80\u5355\u7684\u51fd\u6570\u6765\u83b7\u53d6\u5217\u8868\u7684\u4e2d\u95f4\u5143\u7d20\uff1a\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "def get_middle(some_list):\n",
+ " mid_index = round(len(some_list) / 2)\n",
+ " return some_list[mid_index - 1]\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Python 3.x:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "1\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "get_middle([1]) # looks good\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "2\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "get_middle([1,2,3]) # looks good\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "2\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "get_middle([1,2,3,4,5]) # huh?\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "2.5\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "len([1,2,3,4,5]) / 2 # good\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "2\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "round(len([1,2,3,4,5]) / 2) # why?\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\u4f3c\u4e4e Python \u5c06 2.5 \u820d\u5165\u5230 2\u3002\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e\n",
+ "\n",
+ "- - \u8fd9\u4e0d\u662f\u6d6e\u70b9\u7cbe\u5ea6\u9519\u8bef\uff0c\u5b9e\u9645\u4e0a\uff0c\u8fd9\u79cd\u884c\u4e3a\u662f\u6545\u610f\u7684\u3002\u4ece Python 3.0 \u5f00\u59cb\uff0c`round()` \u4f7f\u7528[\u94f6\u884c\u8fdb\u4f4d\u6cd5](https://en.wikipedia.org/wiki/Rounding#Round_half_to_even)\uff0c\u5176\u4e2d 0.5 \u5c0f\u6570\u56db\u820d\u4e94\u5165\u5230\u6700\u63a5\u8fd1\u7684 **\u5076\u6570** \uff1a\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "0\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "round(0.5)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "2\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "round(1.5)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "2\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "round(2.5)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "0.0\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "import numpy # numpy\u7684\u7ed3\u679c\u4e5f\u662f\u4e00\u6837\n",
+ "numpy.round(0.5)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "2.0\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "numpy.round(1.5)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "2.0\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "numpy.round(2.5)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "- \u8fd9\u662f [IEEE 754](https://en.wikipedia.org/wiki/IEEE_754#Rounding_rules) \u4e2d\u63cf\u8ff0\u7684\u5173\u4e8e0.5\u5206\u4f4d\u820d\u5165\u7684\u63a8\u8350\u65b9\u6cd5\u3002\u7136\u800c\uff0c\u53e6\u4e00\u79cd\u65b9\u6cd5\uff08\u4ece\u96f6\u53d6\u6574\uff09\u5927\u90e8\u5206\u65f6\u95f4\u90fd\u662f\u5728\u5b66\u6821\u6559\u6388\u7684\uff0c\u6240\u4ee5\u94f6\u884c\u8fdb\u4f4d\u6cd5\u53ef\u80fd\u5e76\u4e0d\u4e3a\u4eba\u6240\u77e5\u3002\u6b64\u5916\uff0c\u4e00\u4e9b\u6700\u6d41\u884c\u7684\u7f16\u7a0b\u8bed\u8a00\uff08\u4f8b\u5982\uff1aJavaScript\u3001Java\u3001C/C++\u3001Ruby\u3001Rust\uff09\u4e5f\u4e0d\u4f7f\u7528\u94f6\u884c\u8fdb\u4f4d\u6cd5\u3002\u56e0\u6b64\uff0c\u8fd9\u5bf9 Python \u6765\u8bf4\u8fd8\u662f\u6bd4\u8f83\u7279\u6b8a\u7684\uff0c\u5728\u56db\u820d\u4e94\u5165\u65f6\u53ef\u80fd\u4f1a\u5bfc\u81f4\u6df7\u6dc6\u3002\n",
+ "- \u4e86\u89e3\u66f4\u591a\u4fe1\u606f\uff0c\u8bf7\u53c2\u9605\u6587\u6863 [round()](https://docs.python.org/3/library/functions.html#round) \u6216 [this stackoverflow thread](https://stackoverflow.com/questions/10825926/python -3-x-rounding-behavior) \n",
+ "- \u8bf7\u6ce8\u610f\uff0c`get_middle([1])` \u53ea\u8fd4\u56de1\uff0c\u56e0\u4e3a\u5b83\u7684\u7d22\u5f15\u662f `round(0.5) - 1 = 0 - 1 = -1`\uff0c\u8fd4\u56de\u5217\u8868\u4e2d\u7684\u6700\u540e\u4e00\u4e2a\u5143\u7d20\u3002\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Needles in a Haystack/\u5927\u6d77\u635e\u9488\n",
+ "\u8fc4\u4eca\u4e3a\u6b62\uff0c\u6bcf\u4e00\u4f4dPython\u5f00\u53d1\u8005\u90fd\u4f1a\u9047\u5230\u7c7b\u4f3c\u4ee5\u4e0b\u7684\u60c5\u51b5\u3002\n",
+ "\n",
+ "1\\.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "x, y = (0, 1) if True else None, None\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n",
+ "```\n",
+ ">>> x, y # \u671f\u671b\u7684\u7ed3\u679c\u662f (0, 1)\n",
+ "((0, 1), None)\n",
+ "```\n",
+ "\n",
+ "2\\.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "collapsed": true
+ },
+ "execution_count": null,
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": []
+ }
+ ],
+ "source": [
+ "t = ('one', 'two')\n",
+ "for i in t:\n",
+ " print(i)\n",
+ "\n",
+ "t = ('one')\n",
+ "for i in t:\n",
+ " print(i)\n",
+ "\n",
+ "t = ()\n",
+ "print(t)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "one\n",
+ "two\n",
+ "o\n",
+ "n\n",
+ "e\n",
+ "tuple()\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "3\\.\n",
+ "\n",
+ "```\n",
+ "ten_words_list = [\n",
+ " \"some\",\n",
+ " \"very\",\n",
+ " \"big\",\n",
+ " \"list\",\n",
+ " \"that\"\n",
+ " \"consists\",\n",
+ " \"of\",\n",
+ " \"exactly\",\n",
+ " \"ten\",\n",
+ " \"words\"\n",
+ "]\n",
+ "```\n",
+ "\n",
+ "**Output**\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "9\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "len(ten_words_list)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "4\\. \u4e0d\u591f\u5065\u58ee\u7684\u65ad\u8a00\u673a\u5236\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "a = \"python\"\n",
+ "b = \"javascript\"\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "# \u672a\u5f15\u53d1 AssertionError \n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "# \u5e26\u6709\u5931\u8d25\u8b66\u544a\u4fe1\u606f\u7684assert\u8868\u8fbe\u5f0f\n",
+ "assert(a == b, \"Both languages are different\")\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "5\\.\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "some_list = [1, 2, 3]\n",
+ "some_dict = {\n",
+ " \"key_1\": 1,\n",
+ " \"key_2\": 2,\n",
+ " \"key_3\": 3\n",
+ "}\n",
+ "\n",
+ "some_list = some_list.append(4) \n",
+ "some_dict = some_dict.update({\"key_4\": 4})\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "collapsed": true
+ },
+ "execution_count": null,
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "None\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(some_list)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "collapsed": true
+ },
+ "execution_count": null,
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "None\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(some_dict)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "6\\.\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "def some_recursive_func(a):\n",
+ " if a[0] == 0:\n",
+ " return\n",
+ " a[0] -= 1\n",
+ " some_recursive_func(a)\n",
+ " return a\n",
+ "\n",
+ "def similar_recursive_func(a):\n",
+ " if a == 0:\n",
+ " return a\n",
+ " a -= 1\n",
+ " similar_recursive_func(a)\n",
+ " return a\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[0, 0]\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "some_recursive_func([5, 0])\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "4\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "similar_recursive_func(5)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "* \u5bf9\u4e8e 1, \u6b63\u786e\u7684\u8bed\u53e5\u662f `x, y = (0, 1) if True else (None, None)`.\n",
+ "* \u5bf9\u4e8e 2, \u6b63\u786e\u7684\u8bed\u53e5\u662f `t = ('one',)` \u6216\u8005 `t = 'one',` (\u7f3a\u5c11\u9017\u53f7) \u5426\u5219\u89e3\u91ca\u5668\u4f1a\u8ba4\u4e3a `t` \u662f\u4e00\u4e2a\u5b57\u7b26\u4e32, \u5e76\u9010\u4e2a\u5b57\u7b26\u5bf9\u5176\u8fdb\u884c\u8fed\u4ee3.\n",
+ "* `()` \u662f\u4e00\u4e2a\u7279\u6b8a\u7684\u6807\u8bb0\uff0c\u8868\u793a\u7a7a\u5143\u7ec4.\n",
+ "* \u5bf9\u4e8e 3\uff0c\u6b63\u5982\u60a8\u53ef\u80fd\u5df2\u7ecf\u5f04\u6e05\u695a\u7684\u90a3\u6837\uff0c\u5217\u8868\u4e2d\u7684\u7b2c5\u4e2a\u5143\u7d20\uff08\"that\"\uff09\u540e\u9762\u7f3a\u5c11\u4e00\u4e2a\u9017\u53f7\u3002\u56e0\u6b64\uff0c\u901a\u8fc7\u9690\u5f0f\u5b57\u7b26\u4e32\u5b57\u9762\u8fde\u63a5\uff0c\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " ['some', 'very', 'big', 'list', 'thatconsists', 'of', 'exactly', 'ten', 'words']\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " ten_words_list\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "* \u5728\u7b2c4\u4e2a\u4ee3\u7801\u6bb5\u4e2d\u6ca1\u6709\u5f15\u53d1\"AssertionError\"\uff0c\u56e0\u4e3a\u6211\u4eec\u4e0d\u662f\u65ad\u8a00\u5355\u4e2a\u8868\u8fbe\u5f0f `a == b`\uff0c\u800c\u662f\u65ad\u8a00\u6574\u4e2a\u5143\u7ec4\u3002\u4ee5\u4e0b\u4ee3\u7801\u6bb5\u5c06\u8bf4\u660e\u95ee\u9898\uff0c\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " Traceback (most recent call last):\n",
+ " File \"\", line 1, in \n",
+ " AssertionError\n",
+ " \n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " a = \"python\"\n",
+ " b = \"javascript\"\n",
+ " assert a == b\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " :1: SyntaxWarning: assertion is always true, perhaps remove parentheses?\n",
+ " \n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " assert (a == b, \"Values are not equal\")\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " Traceback (most recent call last):\n",
+ " File \"\", line 1, in \n",
+ " AssertionError: Values are not equal\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " assert a == b, \"Values are not equal\"\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "* \u81f3\u4e8e\u7b2c\u4e94\u4e2a\u7247\u6bb5\uff0c\u5927\u591a\u6570\u4fee\u6539\u5e8f\u5217/\u6620\u5c04\u5bf9\u8c61\u9879\u7684\u65b9\u6cd5\uff0c\u5982`list.append`\u3001`dict.update`\u3001`list.sort`\u7b49\uff0c\u90fd\u5728\u539f\u5730\u4fee\u6539\u5bf9\u8c61\u5e76\u8fd4\u56de`None`\u3002\u8fd9\u80cc\u540e\u7684\u57fa\u672c\u539f\u7406\u662f\u901a\u8fc7\u539f\u5730\u64cd\u4f5c\uff0c\u907f\u514d\u590d\u5236\u5bf9\u8c61\u6765\u63d0\u9ad8\u6027\u80fd(\u53c2\u8003[\u8fd9\u91cc](https://docs.python.org/3/faq/design.html#why-doesn-t-list-sort-return-the-sorted-list))\u3002\n",
+ "* \u6700\u540e\u4e00\u4e2a\u5e94\u8be5\u76f8\u5f53\u660e\u663e\uff0c\u53ef\u53d8\u5bf9\u8c61\uff08\u5982`list`\uff09\u53ef\u4ee5\u5728\u51fd\u6570\u4e2d\u66f4\u6539\uff0c\u4e0d\u53ef\u53d8\u5bf9\u8c61\uff08`a -= 1`\uff09\u7684\u91cd\u65b0\u8d4b\u503c\u5219\u4e0d\u5c5e\u4e8e\u503c\u7684\u6539\u53d8\u3002\n",
+ "* \u4e86\u89e3\u8fd9\u4e9b\u7ec6\u8282\u53ef\u4ee5\u5728\u7a0b\u5e8f\u957f\u671f\u8fd0\u884c\u4e2d\uff0c\u4e3a\u60a8\u8282\u7701\u6570\u5c0f\u65f6\u7684\u8c03\u8bd5\u5de5\u4f5c\u3002\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Splitsies/\u5206\u5272\u51fd\u6570 *\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "['a']\n",
+ "\n",
+ "# is same as\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "'a'.split()\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "['a']\n",
+ "\n",
+ "# but\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "'a'.split(' ')\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "0\n",
+ "\n",
+ "# isn't the same as\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "len(''.split())\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "1\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "len(''.split(' '))\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e\n",
+ "\n",
+ "- \u8d77\u521d\u4eba\u4eec\u53ef\u80fd\u4f1a\u8ba4\u4e3a split \u7684\u9ed8\u8ba4\u5206\u9694\u7b26\u662f\u5355\u4e2a\u7a7a\u683c `' '`\uff0c\u4f46\u6839\u636e [\u6587\u6863](https://docs.python.org/3/library/stdtypes.html#str.split)\uff1a\n",
+ " > \u5982\u679c sep \u672a\u6307\u5b9a\u6216\u4e3a `None`\uff0c\u5219\u5e94\u7528\u4e0d\u540c\u7684\u62c6\u5206\u7b97\u6cd5\uff1a\u8fde\u7eed\u7684\u7a7a\u683c\u88ab\u89c6\u4e3a\u5355\u4e2a\u5206\u9694\u7b26\uff0c\u5982\u679c\u5b57\u7b26\u4e32\u6709\u524d\u5bfc\u6216\u5c3e\u968f\u7a7a\u683c\uff0c\u5219\u7ed3\u679c\u5c06\u5728\u5f00\u5934\u6216\u7ed3\u5c3e\u4e0d\u5305\u542b\u7a7a\u5b57\u7b26\u4e32\u3002\u56e0\u6b64\uff0c\u4f7f\u7528 `None` \u5206\u9694\u7b26\u62c6\u5206\u7a7a\u5b57\u7b26\u4e32\u6216\u4ec5\u5305\u542b\u7a7a\u683c\u7684\u5b57\u7b26\u4e32\u5c06\u8fd4\u56de `[]`\u3002\n",
+ " > \u5982\u679c\u7ed9\u5b9a sep\uff0c\u8fde\u7eed\u7684\u5206\u9694\u7b26\u4e0d\u4f1a\u7ec4\u5408\u5728\u4e00\u8d77\uff0c\u5e76\u88ab\u89c6\u4e3a\u5206\u9694\u7a7a\u5b57\u7b26\u4e32\uff08\u4f8b\u5982\uff0c`'1,,2'.split(',')` \u8fd4\u56de `['1', '', '2 ']`\uff09\u3002\u4f7f\u7528\u6307\u5b9a\u7684\u5206\u9694\u7b26\u62c6\u5206\u7a7a\u5b57\u7b26\u4e32\u4f1a\u8fd4\u56de `['']`\u3002\n",
+ "- Noticing how the leading and trailing whitespaces are handled in the following snippet will make things clear,\n",
+ "- \u6ce8\u610f\u4ee5\u4e0b\u4ee3\u7801\u6bb5\u4e2d\u5982\u4f55\u5904\u7406\u524d\u5bfc\u548c\u5c3e\u968f\u7a7a\u683c\uff0c\u4fc3\u8fdb\u66f4\u6df1\u5165\u7684\u7406\u89e3\uff1a\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " ['', 'a', '']\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " ' a '.split(' ')\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " ['a']\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " ' a '.split()\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " ['']\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " ''.split(' ')\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > All sorted?/\u90fd\u6392\u5e8f\u4e86\u5417\uff1f *\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "False\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "x = 7, 8, 9\n",
+ "sorted(x) == x\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True\n",
+ "\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "sorted(x) == sorted(x)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "False\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "y = reversed(x)\n",
+ "sorted(y) == sorted(y)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e\n",
+ "\n",
+ "- `sorted` \u65b9\u6cd5\u4e00\u5b9a\u8fd4\u56de\u5217\u8868\u7c7b\u578b, \u6bd4\u8f83\u5217\u8868\u4e0e\u5143\u7ec4\u5728Python\u4e2d\u4e00\u5b9a\u8fd4\u56de `False`. \n",
+ "\n",
+ "- ```py\n",
+ " >>> [] == tuple()\n",
+ " False\n",
+ " >>> x = 7, 8, 9\n",
+ " >>> type(x), type(sorted(x))\n",
+ " (tuple, list)\n",
+ " ```\n",
+ "\n",
+ "- \u4e0e `sorted` \u4e0d\u540c\uff0c`reversed` \u65b9\u6cd5\u8fd4\u56de\u4e00\u4e2a\u8fed\u4ee3\u5668\u3002\u4e3a\u4ec0\u4e48\uff1f\u56e0\u4e3a\u6392\u5e8f\u9700\u8981\u5c31\u5730\u4fee\u6539\u8fed\u4ee3\u5668\u6216\u4f7f\u7528\u989d\u5916\u7684\u5bb9\u5668\uff08\u5217\u8868\uff09\uff0c\u800c\u53cd\u5411\u53ef\u4ee5\u7b80\u5355\u5730\u901a\u8fc7\u4ece\u6700\u540e\u4e00\u4e2a\u7d22\u5f15\u8fed\u4ee3\u5230\u7b2c\u4e00\u4e2a\u7d22\u5f15\u6765\u5de5\u4f5c\u3002\n",
+ "\n",
+ "- \u6240\u4ee5\u5728\u6bd4\u8f83 `sorted(y) == sorted(y)` \u65f6\uff0c\u7b2c\u4e00\u6b21\u8c03\u7528 `sorted()` \u4f1a\u6d88\u8017\u8fed\u4ee3\u5668 `y`\uff0c\u4e0b\u4e00\u6b21\u8c03\u7528\u53ea\u4f1a\u8fd4\u56de\u4e00\u4e2a\u7a7a\u5217\u8868\u3002\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " ([7, 8, 9], [])\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " x = 7, 8, 9\n",
+ " y = reversed(x)\n",
+ " sorted(y), sorted(y)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Midnight time doesn't exist?/\u4e0d\u5b58\u5728\u7684\u5348\u591c?\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "from datetime import datetime\n",
+ "\n",
+ "midnight = datetime(2018, 1, 1, 0, 0)\n",
+ "midnight_time = midnight.time()\n",
+ "\n",
+ "noon = datetime(2018, 1, 1, 12, 0)\n",
+ "noon_time = noon.time()\n",
+ "\n",
+ "if midnight_time:\n",
+ " print(\"Time at midnight is\", midnight_time)\n",
+ "\n",
+ "if noon_time:\n",
+ " print(\"Time at noon is\", noon_time)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n",
+ "```sh\n",
+ "('Time at noon is', datetime.time(12, 0))\n",
+ "```\n",
+ "\n",
+ "midnight_time \u5e76\u6ca1\u6709\u88ab\u8f93\u51fa.\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "\n",
+ "\u5728Python 3.5\u4e4b\u524d, \u5982\u679c `datetime.time` \u5bf9\u8c61\u5b58\u50a8\u7684UTC\u7684\u5348\u591c\u65f6\u95f4(\u8bd1: \u5c31\u662f `00:00`), \u90a3\u4e48\u5b83\u7684\u5e03\u5c14\u503c\u4f1a\u88ab\u8ba4\u4e3a\u662f `False`. \u5f53\u4f7f\u7528 `if obj:` \u8bed\u53e5\u6765\u68c0\u67e5 `obj` \u662f\u5426\u4e3a `null` \u6216\u8005\u67d0\u4e9b\u201c\u7a7a\u201d\u503c\u7684\u65f6\u5019, \u5f88\u5bb9\u6613\u51fa\u9519.\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Okay Python, Can you make me fly?/Python, \u53ef\u5426\u5e26\u6211\u98de? *\n",
+ "\u597d, \u53bb\u5427.\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "import antigravity\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n",
+ "\u5618.. \u8fd9\u662f\u4e2a\u8d85\u7ea7\u79d8\u5bc6.\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "+ `antigravity` \u6a21\u5757\u662f Python \u5f00\u53d1\u4eba\u5458\u53d1\u5e03\u7684\u5c11\u6570\u590d\u6d3b\u8282\u5f69\u86cb\u4e4b\u4e00.\n",
+ "+ `import antigravity` \u4f1a\u6253\u5f00\u4e00\u4e2a Python \u7684[\u7ecf\u5178 XKCD \u6f2b\u753b](http://xkcd.com/353/)\u9875\u9762.\n",
+ "+ \u4e0d\u6b62\u5982\u6b64. \u8fd9\u4e2a**\u590d\u6d3b\u8282\u5f69\u86cb\u91cc\u8fd8\u6709\u4e00\u4e2a\u590d\u6d3b\u8282\u5f69\u86cb**. \u5982\u679c\u4f60\u770b\u4e00\u4e0b[\u4ee3\u7801](https://github.com/python/cpython/blob/master/Lib/antigravity.py#L7-L17), \u5c31\u4f1a\u53d1\u73b0\u8fd8\u6709\u4e00\u4e2a\u51fd\u6570\u5b9e\u73b0\u4e86 [XKCD's geohashing \u7b97\u6cd5](https://xkcd.com/426/).\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > `goto`, but why?/`goto`, \u4f46\u4e3a\u4ec0\u4e48? *\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "collapsed": true
+ },
+ "execution_count": null,
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": []
+ }
+ ],
+ "source": [
+ "from goto import goto, label\n",
+ "for i in range(9):\n",
+ " for j in range(9):\n",
+ " for k in range(9):\n",
+ " print(\"I'm trapped, please rescue!\")\n",
+ " if k == 2:\n",
+ " goto .breakout # \u4ece\u591a\u91cd\u5faa\u73af\u4e2d\u8df3\u51fa\n",
+ "label .breakout\n",
+ "print(\"Freedom!\")\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output (Python 2.3):**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "I'm trapped, please rescue!\n",
+ "I'm trapped, please rescue!\n",
+ "Freedom!\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "- 2004\u5e744\u67081\u65e5, Python [\u5ba3\u5e03](https://mail.python.org/pipermail/python-announce-list/2004-April/002982.html) \u52a0\u5165\u4e00\u4e2a\u53ef\u7528\u7684 `goto` \u4f5c\u4e3a\u611a\u4eba\u8282\u793c\u7269.\n",
+ "- \u5f53\u524d\u7248\u672c\u7684 Python \u5e76\u6ca1\u6709\u8fd9\u4e2a\u6a21\u5757.\n",
+ "- \u5c31\u7b97\u53ef\u4ee5\u7528, \u4e5f\u8bf7\u4e0d\u8981\u4f7f\u7528\u5b83. \u8fd9\u91cc\u662f\u4e3a\u4ec0\u4e48Python\u4e2d\u6ca1\u6709 `goto` \u7684[\u539f\u56e0](https://docs.python.org/3/faq/design.html#why-is-there-no-goto).\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Brace yourself!/\u505a\u597d\u601d\u60f3\u51c6\u5907 *\n",
+ "\u5982\u679c\u4f60\u4e0d\u559c\u6b22\u5728Python\u4e2d\u4f7f\u7528\u7a7a\u683c\u6765\u8868\u793a\u4f5c\u7528\u57df, \u4f60\u53ef\u4ee5\u5bfc\u5165 C \u98ce\u683c\u7684 {},\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "from __future__ import braces\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " File \"some_file.py\", line 1\n",
+ " from __future__ import braces\n",
+ "SyntaxError: not a chance\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\u60f3\u7528\u5927\u62ec\u53f7 `braces`? \u6ca1\u95e8! \u89c9\u5f97\u4e0d\u723d, \u8bf7\u53bb\u7528java\u3002\u90a3\u4e48\uff0c\u53e6\u4e00\u4e2a\u4ee4\u4eba\u60ca\u8bb6\u7684\u4e8b\u60c5\uff0c\u627e\u4e00\u627e\u5728 `__future__` \u6a21\u5757\u4e2d\uff0c\u54ea\u91cc\u5f15\u53d1\u4e86 `SyntaxError` [code](https://github.com/python/cpython/blob/master/Lib/__future__.py)?\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "+ \u901a\u5e38 `__future__` \u4f1a\u63d0\u4f9b Python \u672a\u6765\u7248\u672c\u7684\u529f\u80fd. \u7136\u800c\uff0c\u8fd9\u91cc\u7684 \u201c\u672a\u6765\u201d \u662f\u4e00\u4e2a\u8bbd\u523a.\n",
+ "+ \u8fd9\u662f\u4e00\u4e2a\u8868\u8fbe\u793e\u533a\u5bf9\u6b64\u7c7b\u95ee\u9898\u6001\u5ea6\u7684\u590d\u6d3b\u8282\u5f69\u86cb.\n",
+ "+ \u4ee3\u7801\u5b9e\u9645\u4e0a\u5728[`future.c` \u6587\u4ef6]\u4e2d (https://github.com/python/cpython/blob/025eb98dc0c1dc27404df6c544fc2944e0fa9f3a/Python/future.c#L49).\n",
+ "+ \u5f53 CPython \u7f16\u8bd1\u5668\u9047\u5230 [future\u8868\u8fbe\u5f0f](https://docs.python.org/3.3/reference/simple_stmts.html#future-statements) \u65f6\uff0c\u5b83\u9996\u5148\u5728 `future.c` \u4e2d\u8fd0\u884c\u76f8\u5e94\u7684\u4ee3\u7801\uff0c\u7136\u540e\u518d\u5bf9\u5176\u8fdb\u884c\u5904\u7406\u4f5c\u4e3a\u6b63\u5e38\u7684`import`\u8868\u8fbe\u5f0f\u3002\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Let's meet Friendly Language Uncle For Life/\u8ba9\u751f\u6d3b\u66f4\u53cb\u597d *\n",
+ "**Output (Python 3.x)**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " File \"some_file.py\", line 1\n",
+ " \"Ruby\" != \"Python\"\n",
+ " ^\n",
+ "SyntaxError: invalid syntax\n",
+ "\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "from __future__ import barry_as_FLUFL\n",
+ "\"Ruby\" != \"Python\" # \u8fd9\u91cc\u6ca1\u4ec0\u4e48\u7591\u95ee\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "\"Ruby\" <> \"Python\"\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\u8fd9\u5c31\u5bf9\u4e86.\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "- \u76f8\u5173\u7684 [PEP-401](https://www.python.org/dev/peps/pep-0401/) \u53d1\u5e03\u4e8e 2009\u5e744\u67081\u65e5 (\u6240\u4ee5\u4f60\u73b0\u5728\u77e5\u9053\u8fd9\u610f\u5473\u7740\u4ec0\u4e48\u4e86\u5427).\n",
+ "- \u5f15\u7528 PEP-401\n",
+ " > \u610f\u8bc6\u5230 Python 3.0 \u91cc\u7684 != \u8fd0\u7b97\u7b26\u662f\u4e00\u4e2a\u4f1a\u5f15\u8d77\u624b\u6307\u75bc\u75db\u7684\u6050\u6016\u9519\u8bef, FLUFL \u5c06 <> \u8fd0\u7b97\u7b26\u6062\u590d\u4e3a\u552f\u4e00\u5199\u6cd5.\n",
+ "- Uncle Barry \u5728 PEP \u4e2d\u8fd8\u5206\u4eab\u4e86\u5176\u4ed6\u4e1c\u897f; \u4f60\u53ef\u4ee5\u5728[\u8fd9\u91cc](https://www.python.org/dev/peps/pep-0401/)\u83b7\u5f97\u4ed6\u4eec.\n",
+ "- (\u8bd1: \u867d\u7136\u6587\u6863\u4e2d\u6ca1\u5199\uff0c\u4f46\u5e94\u8be5\u662f\u53ea\u80fd\u5728\u4ea4\u4e92\u89e3\u91ca\u5668\u4e2d\u4f7f\u7528.)\n",
+ "- \u5b83\u5728\u4ea4\u4e92\u5f0f\u73af\u5883\u4e2d\u6b63\u5e38\u8fd0\u884c\uff0c\u4f46\u662f\u5f53\u60a8\u901a\u8fc7 python \u6587\u4ef6\u8fd0\u884c\u65f6\u5b83\u4f1a\u5f15\u53d1 `SyntaxError`\uff08\u8bf7\u53c2\u9605\u6b64 [\u95ee\u9898](https://github.com/satwikkansal/wtfpython/issues/94)\uff09\u3002\u60a8\u53ef\u4ee5\u5c06\u8868\u8fbe\u5f0f\u4f5c\u4e3a`eval` \u6216 `compile` \u53c2\u6570\u4e2d\u4f7f\u7528\u3002\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " from __future__ import barry_as_FLUFL\n",
+ " print(eval('\"Ruby\" <> \"Python\"'))\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Even Python understands that love is complicated/\u8fdePython\u4e5f\u77e5\u9053\u7231\u662f\u96be\u8a00\u7684 *\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "import this\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\u7b49\u7b49, **this** \u662f\u4ec0\u4e48? `this` \u662f\u7231 :heart:\n",
+ "\n",
+ "**Output:**\n",
+ "```\n",
+ "The Zen of Python, by Tim Peters\n",
+ "\n",
+ "Beautiful is better than ugly.\n",
+ "\u4f18\u7f8e\u80dc\u4e8e\u4e11\u964b\uff08Python \u4ee5\u7f16\u5199\u4f18\u7f8e\u7684\u4ee3\u7801\u4e3a\u76ee\u6807\uff09\n",
+ "Explicit is better than implicit.\n",
+ "\u660e\u4e86\u80dc\u4e8e\u6666\u6da9\uff08\u4f18\u7f8e\u7684\u4ee3\u7801\u5e94\u5f53\u662f\u660e\u4e86\u7684\uff0c\u547d\u540d\u89c4\u8303\uff0c\u98ce\u683c\u76f8\u4f3c\uff09\n",
+ "Simple is better than complex.\n",
+ "\u7b80\u6d01\u80dc\u4e8e\u590d\u6742\uff08\u4f18\u7f8e\u7684\u4ee3\u7801\u5e94\u5f53\u662f\u7b80\u6d01\u7684\uff0c\u4e0d\u8981\u6709\u590d\u6742\u7684\u5185\u90e8\u5b9e\u73b0\uff09\n",
+ "Complex is better than complicated.\n",
+ "\u590d\u6742\u80dc\u4e8e\u51cc\u4e71\uff08\u5982\u679c\u590d\u6742\u4e0d\u53ef\u907f\u514d\uff0c\u90a3\u4ee3\u7801\u95f4\u4e5f\u4e0d\u80fd\u6709\u96be\u61c2\u7684\u5173\u7cfb\uff0c\u8981\u4fdd\u6301\u63a5\u53e3\u7b80\u6d01\uff09\n",
+ "Flat is better than nested.\n",
+ "\u6241\u5e73\u80dc\u4e8e\u5d4c\u5957\uff08\u4f18\u7f8e\u7684\u4ee3\u7801\u5e94\u5f53\u662f\u6241\u5e73\u7684\uff0c\u4e0d\u80fd\u6709\u592a\u591a\u7684\u5d4c\u5957\uff09\n",
+ "Sparse is better than dense.\n",
+ "\u95f4\u9694\u80dc\u4e8e\u7d27\u51d1\uff08\u4f18\u7f8e\u7684\u4ee3\u7801\u6709\u9002\u5f53\u7684\u95f4\u9694\uff0c\u4e0d\u8981\u5962\u671b\u4e00\u884c\u4ee3\u7801\u89e3\u51b3\u95ee\u9898\uff09\n",
+ "Readability counts.\n",
+ "\u53ef\u8bfb\u6027\u5f88\u91cd\u8981\uff08\u4f18\u7f8e\u7684\u4ee3\u7801\u4e00\u5b9a\u662f\u53ef\u8bfb\u7684\uff09\n",
+ "Special cases aren't special enough to break the rules.\n",
+ "\u6ca1\u6709\u7279\u4f8b\u7279\u6b8a\u5230\u9700\u8981\u8fdd\u80cc\u8fd9\u4e9b\u89c4\u5219\uff08\u8fd9\u4e9b\u89c4\u5219\u81f3\u9ad8\u65e0\u4e0a\uff09\n",
+ "Although practicality beats purity.\n",
+ "\u5c3d\u7ba1\u6211\u4eec\u66f4\u503e\u5411\u4e8e\u5b9e\u7528\u6027\n",
+ "Errors should never pass silently.\n",
+ "\u4e0d\u8981\u5b89\u9759\u7684\u5305\u5bb9\u6240\u6709\u9519\u8bef\n",
+ "Unless explicitly silenced.\n",
+ "\u9664\u975e\u4f60\u786e\u5b9a\u9700\u8981\u8fd9\u6837\u505a\uff08\u7cbe\u51c6\u5730\u6355\u83b7\u5f02\u5e38\uff0c\u4e0d\u5199 except:pass \u98ce\u683c\u7684\u4ee3\u7801\uff09\n",
+ "In the face of ambiguity, refuse the temptation to guess.\n",
+ "\u62d2\u7edd\u8bf1\u60d1\u4f60\u53bb\u731c\u6d4b\u7684\u66a7\u6627\u4e8b\u7269\n",
+ "There should be one-- and preferably only one --obvious way to do it.\n",
+ "\u800c\u662f\u5c3d\u91cf\u627e\u4e00\u79cd\uff0c\u6700\u597d\u662f\u552f\u4e00\u4e00\u79cd\u660e\u663e\u7684\u89e3\u51b3\u65b9\u6848\uff08\u5982\u679c\u4e0d\u786e\u5b9a\uff0c\u5c31\u7528\u7a77\u4e3e\u6cd5\uff09\n",
+ "Although that way may not be obvious at first unless you're Dutch.\n",
+ "\u867d\u7136\u8fd9\u5e76\u4e0d\u5bb9\u6613\uff0c\u56e0\u4e3a\u4f60\u4e0d\u662f Python \u4e4b\u7236\uff08\u8fd9\u91cc\u7684 Dutch \u662f\u6307 Guido \uff09\n",
+ "Now is better than never.\n",
+ "\u73b0\u5728\u884c\u52a8\u597d\u8fc7\u6c38\u8fdc\u4e0d\u884c\u52a8\n",
+ "Although never is often better than *right* now.\n",
+ "\u5c3d\u7ba1\u4e0d\u884c\u52a8\u8981\u597d\u8fc7\u9c81\u83bd\u884c\u52a8\n",
+ "If the implementation is hard to explain, it's a bad idea.\n",
+ "\u5982\u679c\u4f60\u65e0\u6cd5\u5411\u4eba\u63cf\u8ff0\u4f60\u7684\u65b9\u6848\uff0c\u90a3\u80af\u5b9a\u4e0d\u662f\u4e00\u4e2a\u597d\u65b9\u6848\uff1b\n",
+ "If the implementation is easy to explain, it may be a good idea.\n",
+ "\u5982\u679c\u4f60\u80fd\u8f7b\u677e\u5411\u4eba\u63cf\u8ff0\u4f60\u7684\u65b9\u6848\uff0c\u90a3\u4e5f\u8bb8\u4f1a\u662f\u4e00\u4e2a\u597d\u65b9\u6848\uff08\u65b9\u6848\u6d4b\u8bc4\u6807\u51c6\uff09\n",
+ "Namespaces are one honking great idea -- let's do more of those!\n",
+ "\u547d\u540d\u7a7a\u95f4\u662f\u4e00\u79cd\u7edd\u5999\u7684\u7406\u5ff5\uff0c\u6211\u4eec\u5e94\u5f53\u591a\u52a0\u5229\u7528\uff08\u5021\u5bfc\u4e0e\u53f7\u53ec\uff09\n",
+ "```\n",
+ "\n",
+ "\u8fd9\u662f Python \u4e4b\u7985!\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "love = this\n",
+ "this is love\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "False\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "love is True\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "False\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "love is False\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "love is not True or False\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "love is not True or False; love is love # \u7231\u662f\u96be\u8a00\u7684\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "\n",
+ "* `this` \u6a21\u5757\u662f\u5173\u4e8e Python \u4e4b\u7985\u7684\u590d\u6d3b\u8282\u5f69\u86cb ([PEP 20](https://www.python.org/dev/peps/pep-0020)).\n",
+ "* \u5982\u679c\u4f60\u8ba4\u4e3a\u8fd9\u5df2\u7ecf\u591f\u6709\u8da3\u7684\u4e86, \u53ef\u4ee5\u770b\u770b [this.py](https://hg.python.org/cpython/file/c3896275c0f6/Lib/this.py) \u7684\u5b9e\u73b0. \u6709\u8da3\u7684\u662f, Python \u4e4b\u7985\u7684\u5b9e\u73b0\u4ee3\u7801\u8fdd\u53cd\u4e86\u4ed6\u81ea\u5df1 (\u8fd9\u53ef\u80fd\u662f\u552f\u4e00\u4f1a\u53d1\u751f\u8fd9\u79cd\u60c5\u51b5\u7684\u5730\u65b9).\n",
+ "*\n",
+ "\u81f3\u4e8e `love is not True or False; love is love`, \u610f\u5916\u5374\u53c8\u4e0d\u8a00\u800c\u55bb.\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Yes, it exists!/\u662f\u7684, \u5b83\u5b58\u5728!\n",
+ "**\u5faa\u73af\u7684 `else`.** \u4e00\u4e2a\u5178\u578b\u7684\u4f8b\u5b50:\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " def does_exists_num(l, to_find):\n",
+ " for num in l:\n",
+ " if num == to_find:\n",
+ " print(\"Exists!\")\n",
+ " break\n",
+ " else:\n",
+ " print(\"Does not exist\")\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "Exists!\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "some_list = [1, 2, 3, 4, 5]\n",
+ "does_exists_num(some_list, 4)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "Does not exist\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "does_exists_num(some_list, -1)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**\u5f02\u5e38\u7684 `else` .** \u4f8b,\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "try:\n",
+ " pass\n",
+ "except:\n",
+ " print(\"Exception occurred!!!\")\n",
+ "else:\n",
+ " print(\"Try block executed successfully...\")\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "Try block executed successfully...\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "- \u5faa\u73af\u540e\u7684 `else` \u5b50\u53e5\u53ea\u4f1a\u5728\u5faa\u73af\u6ca1\u6709\u89e6\u53d1 `break` \u8bed\u53e5, \u6b63\u5e38\u7ed3\u675f\u7684\u60c5\u51b5\u4e0b\u624d\u4f1a\u6267\u884c.\n",
+ "- try \u4e4b\u540e\u7684 `else` \u5b50\u53e5\u4e5f\u88ab\u79f0\u4e3a \"\u5b8c\u6210\u5b50\u53e5\", \u56e0\u4e3a\u5728 `try` \u8bed\u53e5\u4e2d\u5230\u8fbe `else` \u5b50\u53e5\u610f\u5473\u7740try\u5757\u5b9e\u9645\u4e0a\u5df2\u6210\u529f\u5b8c\u6210.\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Ellipsis/\u7701\u7565 *\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "def some_func():\n",
+ " Ellipsis\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "# \u6ca1\u6709\u8f93\u51fa\uff0c\u4e5f\u6ca1\u6709\u62a5\u9519\n",
+ "\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "some_func()\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "Traceback (most recent call last):\n",
+ " File \"\", line 1, in \n",
+ "NameError: name 'SomeRandomString' is not defined\n",
+ "\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "SomeRandomString\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "Ellipsis\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "Ellipsis\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e\n",
+ "- \u5728 Python \u4e2d\uff0c`Ellipsis` \u662f\u4e00\u4e2a\u5168\u5c40\u53ef\u7528\u7684\u5185\u7f6e\u5bf9\u8c61\uff0c\u76f8\u5f53\u4e8e`...`\u3002\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " Ellipsis\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " ...\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "- \u7701\u7565\u53f7\u53ef\u7528\u4e8e\u591a\u79cd\u7528\u9014\uff0c\n",
+ " + \u4f5c\u4e3a\u5c1a\u672a\u7f16\u5199\u7684\u4ee3\u7801\u7684\u5360\u4f4d\u7b26\uff08\u5c31\u50cf`pass`\u8bed\u53e5\uff09\n",
+ " + \u5728\u5207\u7247\u8bed\u6cd5\u4e2d\u8868\u793a\u5b8c\u6574\u5207\u7247\u7684\u5176\u4f59\u7ef4\u5ea6\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " array([\n",
+ " [\n",
+ " [0, 1],\n",
+ " [2, 3]\n",
+ " ],\n",
+ "\n",
+ " [\n",
+ " [4, 5],\n",
+ " [6, 7]\n",
+ " ]\n",
+ " ])\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " import numpy as np\n",
+ " three_dimensional_array = np.arange(8).reshape(2, 2, 2)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ " \u6240\u4ee5\u6211\u4eec\u7684 `three_dimensional_array` \u662f\u4e00\u4e2a\u6570\u7ec4\u7684\u6570\u7ec4\u7684\u6570\u7ec4\u3002\u5047\u8bbe\u6211\u4eec\u8981\u6253\u5370\u6240\u6709\u6700\u5185\u5c42\u6570\u7ec4\u7684\u7b2c\u4e8c\u4e2a\u5143\u7d20\uff08\u7d22\u5f15 `1`\uff09\uff0c\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528 Ellipsis \u7ed5\u8fc7\u6240\u6709\u524d\u9762\u7684\u7ef4\u5ea6\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " array([[1, 3],\n",
+ " [5, 7]])\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " three_dimensional_array[:,:,1]\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " array([[1, 3],\n",
+ " [5, 7]])\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " three_dimensional_array[..., 1] # \u4f7f\u7528Ellipsis.\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ " \u6ce8\u610f\uff1a\u8fd9\u9002\u7528\u4e8e\u4efb\u610f\u6570\u91cf\u7684\u7ef4\u5ea6\u3002\u60a8\u751a\u81f3\u53ef\u4ee5\u5728\u7b2c\u4e00\u4e2a\u548c\u6700\u540e\u4e00\u4e2a\u7ef4\u5ea6\u4e2d\u9009\u62e9\u5207\u7247\u5e76\u4ee5\u8fd9\u79cd\u65b9\u5f0f\u5ffd\u7565\u4e2d\u95f4\u7684\u5207\u7247(`n_dimensional_array[firs_dim_slice, ..., last_dim_slice]`)\n",
+ "\n",
+ " + \u5728 [\u7c7b\u578b\u63d0\u793a](https://docs.python.org/3/library/typing.html)\u4e2d\u4ec5\u8868\u793a\u7c7b\u578b\u7684\u4e00\u90e8\u5206\uff08\u5982 `(Callable[..., int]` \u6216 `Tuple[ str, ...]`))\n",
+ "\n",
+ " + \u60a8\u4e5f\u53ef\u4ee5\u4f7f\u7528\u7701\u7565\u53f7\u4f5c\u4e3a\u9ed8\u8ba4\u51fd\u6570\u53c2\u6570\uff08\u5728\u60a8\u60f3\u8981\u533a\u5206\u201c\u65e0\u53c2\u6570\u201d\u548c\u201c\u4f20\u9012None\u503c\u201d\u573a\u666f\u7684\u60c5\u51b5\u4e0b\uff09\u3002\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Inpinity/\u65e0\u9650 *\n",
+ "\u82f1\u6587\u62fc\u5199\u662f\u6709\u610f\u7684, \u8bf7\u4e0d\u8981\u4e3a\u6b64\u63d0\u4ea4\u8865\u4e01.\n",
+ "(\u8bd1: \u8fd9\u91cc\u662f\u4e3a\u4e86\u7a81\u51fa Python \u4e2d\u65e0\u9650\u7684\u5b9a\u4e49\u4e0e[Pi](https://en.wikipedia.org/wiki/Pi)\u6709\u5173, \u6240\u4ee5\u5c06\u4e24\u4e2a\u5355\u8bcd\u62fc\u63a5\u4e86.)\n",
+ "\n",
+ "**Output (Python 3.x):**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "314159\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "infinity = float('infinity')\n",
+ "hash(infinity)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "-314159\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "hash(float('-inf'))\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "- infinity \u7684\u54c8\u5e0c\u503c\u662f 10\u2075 x \u03c0.\n",
+ "- \u6709\u610f\u601d\u7684\u662f, `float('-inf')` \u7684\u54c8\u5e0c\u503c\u5728 Python 3 \u4e2d\u662f \"-10\u2075 x \u03c0\" , \u800c\u5728 Python 2 \u4e2d\u662f \"-10\u2075 x e\".\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Let's mangle/\u4fee\u9970\u65f6\u95f4! *\n",
+ "1\\.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "class Yo(object):\n",
+ " def __init__(self):\n",
+ " self.__honey = True\n",
+ " self.bro = True\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "Yo().bro\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "AttributeError: 'Yo' object has no attribute '__honey'\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "Yo().__honey\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "Yo()._Yo__honey\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "2\\.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "class Yo(object):\n",
+ " def __init__(self):\n",
+ " # \u8fd9\u6b21\u8bd5\u8bd5\u5bf9\u79f0\u5f62\u5f0f\n",
+ " self.__honey__ = True\n",
+ " self.bro = True\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True\n",
+ "\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "Yo().bro\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "Traceback (most recent call last):\n",
+ " File \"\", line 1, in \n",
+ "AttributeError: 'Yo' object has no attribute '_Yo__honey__'\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "Yo()._Yo__honey__\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\u4e3a\u4ec0\u4e48 `Yo()._Yo__honey` \u80fd\u8fd0\u884c? \u53ea\u6709\u5370\u5ea6\u4eba\u7406\u89e3.(\u8bd1: \u8fd9\u4e2a\u6897\u53ef\u80fd\u662f\u6307\u5370\u5ea6\u97f3\u4e50\u4eba[Yo Yo Honey Singh](https://en.wikipedia.org/wiki/Yo_Yo_Honey_Singh))\n",
+ "\n",
+ "\n",
+ "3\\.\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "_A__variable = \"Some value\"\n",
+ "\n",
+ "class A(object):\n",
+ " def some_func(self):\n",
+ " return __variable # \u6ca1\u5728\u4efb\u4f55\u5730\u65b9\u521d\u59cb\u5316\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "Traceback (most recent call last):\n",
+ " File \"\", line 1, in \n",
+ "AttributeError: 'A' object has no attribute '__variable'\n",
+ "\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "A().__variable\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "'Some value'\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "A().some_func()\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "\n",
+ "* [\u547d\u540d\u4fee\u9970](https://en.wikipedia.org/wiki/Name_mangling) \u7528\u4e8e\u907f\u514d\u4e0d\u540c\u547d\u540d\u7a7a\u95f4\u4e4b\u95f4\u540d\u79f0\u51b2\u7a81.\n",
+ "* \u5728 Python \u4e2d, \u89e3\u91ca\u5668\u4f1a\u901a\u8fc7\u7ed9\u7c7b\u4e2d\u4ee5 `__` (\u53cc\u4e0b\u5212\u7ebf)\u5f00\u5934\u4e14\u7ed3\u5c3e\u6700\u591a\u53ea\u6709\u4e00\u4e2a\u4e0b\u5212\u7ebf\u7684\u7c7b\u6210\u5458\u540d\u79f0\u52a0\u4e0a`_NameOfTheClass` \u6765\u4fee\u9970(mangles)\u540d\u79f0.\n",
+ "* \u6240\u4ee5, \u8981\u8bbf\u95ee `__honey` \u5bf9\u8c61,\u6211\u4eec\u9700\u8981\u52a0\u4e0a `_Yo` \u4ee5\u9632\u6b62\u4e0e\u5176\u4ed6\u7c7b\u4e2d\u5b9a\u4e49\u7684\u76f8\u540c\u540d\u79f0\u7684\u5c5e\u6027\u53d1\u751f\u51b2\u7a81.\n",
+ "* \u4f46\u662f\u4e3a\u4ec0\u4e48\u5b83\u5728\u7b2c\u4e8c\u4e2a\u7247\u6bb5\u4e2d\u4e0d\u8d77\u4f5c\u7528\uff1f \u56e0\u4e3a\u547d\u540d\u4fee\u9970\u6392\u9664\u4e86\u4ee5\u53cc\u4e0b\u5212\u7ebf\u7ed3\u5c3e\u7684\u540d\u79f0\u3002\n",
+ "* \u7b2c\u4e09\u4e2a\u7247\u6bb5\u4e5f\u662f\u547d\u540d\u4fee\u9970\u7684\u7ed3\u679c\u3002 `return __variable` \u8bed\u53e5\u4e2d\u7684 `__variable` \u540d\u79f0\u88ab\u4fee\u6539\u4e3a `_A__variable`\uff0c\u8fd9\u4e5f\u6070\u597d\u662f\u6211\u4eec\u5728\u5916\u90e8\u4f5c\u7528\u57df\u4e2d\u58f0\u660e\u7684\u53d8\u91cf\u7684\u540d\u79f0\u3002\n",
+ "* \u6b64\u5916\uff0c\u5982\u679c\u4fee\u9970\u540e\u7684\u53d8\u91cf\u540d\u8d85\u8fc7255\u4e2a\u5b57\u7b26\uff0c\u5219\u4f1a\u8fdb\u884c\u622a\u65ad\u3002\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Skipping lines?/\u8df3\u8fc7\u4e00\u884c?\n",
+ "**Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "11\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "value = 11\n",
+ "valu\u0435 = 32\n",
+ "value\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\u4ec0\u4e48\u9b3c?\n",
+ "\n",
+ "**\u6ce8\u610f:** \u5982\u679c\u4f60\u60f3\u8981\u91cd\u73b0\u7684\u8bdd\u6700\u7b80\u5355\u7684\u65b9\u6cd5\u662f\u76f4\u63a5\u590d\u5236\u4e0a\u9762\u7684\u4ee3\u7801\u7247\u6bb5\u5230\u4f60\u7684\u6587\u4ef6\u6216\u547d\u4ee4\u884c\u91cc.\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "\n",
+ "\u4e00\u4e9b\u975e\u897f\u65b9\u5b57\u7b26\u867d\u7136\u770b\u8d77\u6765\u548c\u82f1\u8bed\u5b57\u6bcd\u76f8\u540c, \u4f46\u4f1a\u88ab\u89e3\u91ca\u5668\u8bc6\u522b\u4e3a\u4e0d\u540c\u7684\u5b57\u6bcd.\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "1077\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "ord('\u0435') # \u897f\u91cc\u5c14\u8bed\u7684 'e' (Ye)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "101\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "ord('e') # \u62c9\u4e01\u8bed\u7684 'e', \u7528\u4e8e\u82f1\u6587\u5e76\u4f7f\u7528\u6807\u51c6\u952e\u76d8\u8f93\u5165\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "False\n",
+ "\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "'\u0435' == 'e'\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "42\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "value = 42 # \u62c9\u4e01\u8bed e\n",
+ "valu\u0435 = 23 # \u897f\u91cc\u5c14\u8bed 'e', Python 2.x \u7684\u89e3\u91ca\u5668\u5728\u8fd9\u4f1a\u629b\u51fa `SyntaxError` \u5f02\u5e38\n",
+ "value\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\u5185\u7f6e\u7684 `ord()` \u51fd\u6570\u53ef\u4ee5\u8fd4\u56de\u4e00\u4e2a\u5b57\u7b26\u7684 Unicode [\u4ee3\u7801\u70b9](https://en.wikipedia.org/wiki/Code_point), \u8fd9\u91cc\u897f\u91cc\u5c14\u8bed 'e' \u548c\u62c9\u4e01\u8bed 'e' \u7684\u4ee3\u7801\u70b9\u4e0d\u540c\u8bc1\u5b9e\u4e86\u4e0a\u8ff0\u4f8b\u5b50.\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Teleportation/\u7a7a\u95f4\u79fb\u52a8 *\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "import numpy as np\n",
+ "\n",
+ "def energy_send(x):\n",
+ " # \u521d\u59cb\u5316\u4e00\u4e2a numpy \u6570\u7ec4\n",
+ " np.array([float(x)])\n",
+ "\n",
+ "def energy_receive():\n",
+ " # \u8fd4\u56de\u4e00\u4e2a\u7a7a\u7684 numpy \u6570\u7ec4\n",
+ " return np.empty((), dtype=np.float).tolist()\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "123.456\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "energy_send(123.456)\n",
+ "energy_receive()\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\u8c01\u6765\u7ed9\u6211\u53d1\u4e2a\u8bfa\u8d1d\u5c14\u5956?\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "\n",
+ "* \u6ce8\u610f\u5728 `energy_send` \u51fd\u6570\u4e2d\u521b\u5efa\u7684 numpy \u6570\u7ec4\u5e76\u6ca1\u6709\u8fd4\u56de, \u56e0\u6b64\u5185\u5b58\u7a7a\u95f4\u88ab\u91ca\u653e\u5e76\u53ef\u4ee5\u88ab\u91cd\u65b0\u5206\u914d.\n",
+ "* `numpy.empty()` \u76f4\u63a5\u8fd4\u56de\u4e0b\u4e00\u6bb5\u7a7a\u95f2\u5185\u5b58\uff0c\u800c\u4e0d\u91cd\u65b0\u521d\u59cb\u5316. \u800c\u8fd9\u4e2a\u5185\u5b58\u70b9\u6070\u597d\u5c31\u662f\u521a\u521a\u91ca\u653e\u7684\u90a3\u4e2a(\u901a\u5e38\u60c5\u51b5\u4e0b, \u5e76\u4e0d\u7edd\u5bf9).\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Well, something is fishy.../\u55ef\uff0c\u6709\u4e9b\u53ef\u7591...\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "def square(x):\n",
+ " \"\"\"\n",
+ " \u4e00\u4e2a\u901a\u8fc7\u52a0\u6cd5\u8ba1\u7b97\u5e73\u65b9\u7684\u7b80\u5355\u51fd\u6570.\n",
+ " \"\"\"\n",
+ " sum_so_far = 0\n",
+ " for counter in range(x):\n",
+ " sum_so_far = sum_so_far + x\n",
+ " return sum_so_far\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output (Python 2.x):**\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "10\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "square(10)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\u96be\u9053\u4e0d\u5e94\u8be5\u662f100\u5417?\n",
+ "\n",
+ "**\u6ce8\u610f:** \u5982\u679c\u4f60\u65e0\u6cd5\u91cd\u73b0, \u53ef\u4ee5\u5c1d\u8bd5\u8fd0\u884c\u8fd9\u4e2a\u6587\u4ef6[mixed_tabs_and_spaces.py](/mixed_tabs_and_spaces.py).\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "\n",
+ "* **\u4e0d\u8981\u6df7\u7528\u5236\u8868\u7b26(tab)\u548c\u7a7a\u683c(space)!** \u5728\u4e0a\u9762\u7684\u4f8b\u5b50\u4e2d, return \u7684\u524d\u9762\u662f\"1\u4e2a\u5236\u8868\u7b26\", \u800c\u5176\u4ed6\u90e8\u5206\u7684\u4ee3\u7801\u524d\u9762\u662f \"4\u4e2a\u7a7a\u683c\".\n",
+ "* Python\u662f\u8fd9\u4e48\u5904\u7406\u5236\u8868\u7b26\u7684:\n",
+ " > \u9996\u5148, \u5236\u8868\u7b26\u4f1a\u4ece\u5de6\u5230\u53f3\u4f9d\u6b21\u88ab\u66ff\u6362\u62108\u4e2a\u7a7a\u683c, \u76f4\u5230\u88ab\u66ff\u6362\u540e\u7684\u5b57\u7b26\u603b\u6570\u662f\u516b\u7684\u500d\u6570 <...>\n",
+ "* \u56e0\u6b64, `square` \u51fd\u6570\u6700\u540e\u4e00\u884c\u7684\u5236\u8868\u7b26\u4f1a\u88ab\u66ff\u6362\u62108\u4e2a\u7a7a\u683c, \u5bfc\u81f4return\u8bed\u53e5\u8fdb\u5165\u5faa\u73af\u8bed\u53e5\u91cc\u9762.\n",
+ "* Python 3 \u5f88\u53cb\u597d, \u5728\u8fd9\u79cd\u60c5\u51b5\u4e0b\u4f1a\u81ea\u52a8\u629b\u51fa\u9519\u8bef.\n",
+ "\n",
+ " **Output (Python 3.x):**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " TabError: inconsistent use of tabs and spaces in indentation\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > `+=` is faster/\u66f4\u5feb\u7684 `+=`\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "0.25748300552368164\n",
+ "# \u7528 \"+=\" \u8fde\u63a5\u4e09\u4e2a\u5b57\u7b26\u4e32:\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "# \u7528 \"+\" \u8fde\u63a5\u4e09\u4e2a\u5b57\u7b26\u4e32:\n",
+ "timeit.timeit(\"s1 = s1 + s2 + s3\", setup=\"s1 = ' ' * 100000; s2 = ' ' * 100000; s3 = ' ' * 100000\", number=100)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "0.012188911437988281\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "timeit.timeit(\"s1 += s2 + s3\", setup=\"s1 = ' ' * 100000; s2 = ' ' * 100000; s3 = ' ' * 100000\", number=100)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "+ \u8fde\u63a5\u4e24\u4e2a\u4ee5\u4e0a\u7684\u5b57\u7b26\u4e32\u65f6 `+=` \u6bd4 `+` \u66f4\u5feb, \u56e0\u4e3a\u5728\u8ba1\u7b97\u8fc7\u7a0b\u4e2d\u7b2c\u4e00\u4e2a\u5b57\u7b26\u4e32 (\u4f8b\u5982, `s1 += s2 + s3` \u4e2d\u7684 `s1`) \u4e0d\u4f1a\u88ab\u9500\u6bc1.(\u8bd1: \u5c31\u662f `+=` \u6267\u884c\u7684\u662f\u8ffd\u52a0\u64cd\u4f5c\uff0c\u5c11\u4e86\u4e00\u4e2a\u9500\u6bc1\u65b0\u5efa\u7684\u52a8\u4f5c.)\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Let's make a giant string!/\u6765\u505a\u4e2a\u5de8\u5927\u7684\u5b57\u7b26\u4e32\u5427\uff01\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "def add_string_with_plus(iters):\n",
+ " s = \"\"\n",
+ " for i in range(iters):\n",
+ " s += \"xyz\"\n",
+ " assert len(s) == 3*iters\n",
+ "\n",
+ "def add_bytes_with_plus(iters):\n",
+ " s = b\"\"\n",
+ " for i in range(iters):\n",
+ " s += b\"xyz\"\n",
+ " assert len(s) == 3*iters\n",
+ "\n",
+ "def add_string_with_format(iters):\n",
+ " fs = \"{}\"*iters\n",
+ " s = fs.format(*([\"xyz\"]*iters))\n",
+ " assert len(s) == 3*iters\n",
+ "\n",
+ "def add_string_with_join(iters):\n",
+ " l = []\n",
+ " for i in range(iters):\n",
+ " l.append(\"xyz\")\n",
+ " s = \"\".join(l)\n",
+ " assert len(s) == 3*iters\n",
+ "\n",
+ "def convert_list_to_string(l, iters):\n",
+ " s = \"\".join(l)\n",
+ " assert len(s) == 3*iters\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "1000 loops, best of 3: 972 \u00b5s per loop\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "timeit(add_string_with_plus(10000))\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "1000 loops, best of 3: 815 \u00b5s per loop\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "timeit(add_bytes_with_plus(10000))\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "1000 loops, best of 3: 508 \u00b5s per loop\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "timeit(add_string_with_format(10000))\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "1000 loops, best of 3: 878 \u00b5s per loop\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "timeit(add_string_with_join(10000))\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "10000 loops, best of 3: 80 \u00b5s per loop\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "l = [\"xyz\"]*10000\n",
+ "timeit(convert_list_to_string(l, 10000))\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\u8ba9\u6211\u4eec\u5c06\u8fed\u4ee3\u6b21\u6570\u589e\u52a010\u500d.\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "100 loops, best of 3: 9.75 ms per loop\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "timeit(add_string_with_plus(100000)) # \u6267\u884c\u65f6\u95f4\u7ebf\u6027\u589e\u52a0\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "1000 loops, best of 3: 974 ms per loop\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "timeit(add_bytes_with_plus(100000)) # \u4e8c\u6b21\u589e\u52a0\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "100 loops, best of 3: 5.25 ms per loop\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "timeit(add_string_with_format(100000)) # \u7ebf\u6027\u589e\u52a0\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "100 loops, best of 3: 9.85 ms per loop\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "timeit(add_string_with_join(100000)) # \u7ebf\u6027\u589e\u52a0\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "1000 loops, best of 3: 723 \u00b5s per loop\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "l = [\"xyz\"]*100000\n",
+ "timeit(convert_list_to_string(l, 100000)) # \u7ebf\u6027\u589e\u52a0\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e:\n",
+ "- \u4f60\u53ef\u4ee5\u5728\u8fd9\u83b7\u5f97\u66f4\u591a [timeit](https://docs.python.org/3/library/timeit.html) \u7684\u76f8\u5173\u4fe1\u606f. \u5b83\u901a\u5e38\u7528\u4e8e\u8861\u91cf\u4ee3\u7801\u7247\u6bb5\u7684\u6267\u884c\u65f6\u95f4.\n",
+ "- \u4e0d\u8981\u7528 `+` \u53bb\u751f\u6210\u8fc7\u957f\u7684\u5b57\u7b26\u4e32, \u5728 Python \u4e2d, `str` \u662f\u4e0d\u53ef\u53d8\u7684, \u6240\u4ee5\u5728\u6bcf\u6b21\u8fde\u63a5\u4e2d\u4f60\u90fd\u8981\u628a\u5de6\u53f3\u4e24\u4e2a\u5b57\u7b26\u4e32\u590d\u5236\u5230\u65b0\u7684\u5b57\u7b26\u4e32\u4e2d. \u5982\u679c\u4f60\u8fde\u63a5\u56db\u4e2a\u957f\u5ea6\u4e3a10\u7684\u5b57\u7b26\u4e32, \u4f60\u9700\u8981\u62f7\u8d1d (10+10) + ((10+10)+10) + (((10+10)+10)+10) = 90 \u4e2a\u5b57\u7b26\u800c\u4e0d\u662f 40 \u4e2a\u5b57\u7b26. \u968f\u7740\u5b57\u7b26\u4e32\u7684\u6570\u91cf\u548c\u5927\u5c0f\u7684\u589e\u52a0, \u60c5\u51b5\u4f1a\u53d8\u5f97\u8d8a\u53d1\u7684\u7cdf\u7cd5 (\u5c31\u50cf`add_bytes_with_plus` \u51fd\u6570\u7684\u6267\u884c\u65f6\u95f4\u4e00\u6837)\n",
+ "- \u56e0\u6b64, \u66f4\u5efa\u8bae\u4f7f\u7528 `.format.` \u6216 `%` \u8bed\u6cd5 (\u4f46\u662f, \u5bf9\u4e8e\u77ed\u5b57\u7b26\u4e32, \u5b83\u4eec\u6bd4 `+` \u7a0d\u6162\u4e00\u70b9).\n",
+ "- \u53c8\u6216\u8005, \u5982\u679c\u4f60\u6240\u9700\u7684\u5185\u5bb9\u5df2\u7ecf\u4ee5\u53ef\u8fed\u4ee3\u5bf9\u8c61\u7684\u5f62\u5f0f\u63d0\u4f9b\u4e86, \u4f7f\u7528 `''.join(\u53ef\u8fed\u4ee3\u5bf9\u8c61)` \u8981\u5feb\u591a\u4e86.\n",
+ "- `add_string_with_plus` \u7684\u6267\u884c\u65f6\u95f4\u6ca1\u6709\u50cf `add_bytes_with_plus` \u4e00\u6837\u51fa\u73b0\u4e8c\u6b21\u589e\u52a0\u662f\u56e0\u4e3a\u89e3\u91ca\u5668\u4f1a\u5982\u540c\u4e0a\u4e00\u4e2a\u4f8b\u5b50\u6240\u8ba8\u8bba\u7684\u4e00\u6837\u4f18\u5316 `+=`. \u7528 `s = s + \"x\" + \"y\" + \"z\"` \u66ff\u4ee3 `s += \"xyz\"` \u7684\u8bdd, \u6267\u884c\u65f6\u95f4\u5c31\u4f1a\u4e8c\u6b21\u589e\u52a0\u4e86.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " 100 loops, best of 3: 9.87 ms per loop\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " def add_string_with_plus(iters):\n",
+ " s = \"\"\n",
+ " for i in range(iters):\n",
+ " s = s + \"x\" + \"y\" + \"z\"\n",
+ " assert len(s) == 3*iters\n",
+ "\n",
+ " timeit(add_string_with_plus(10000))\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ " 1 loops, best of 3: 1.09 s per loop\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ " timeit(add_string_with_plus(100000)) # \u6267\u884c\u65f6\u95f4\u4e8c\u6b21\u589e\u52a0\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Slowing down `dict` lookups/\u8ba9\u5b57\u5178\u7684\u67e5\u627e\u6162\u4e0b\u6765 *\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "some_dict = {str(i): 1 for i in range(1_000_000)}\n",
+ "another_dict = {str(i): 1 for i in range(1_000_000)}\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:**\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "28.6 ns \u00b1 0.115 ns per loop (mean \u00b1 std. dev. of 7 runs, 10000000 loops each)\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "%timeit some_dict['5']\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "37.2 ns \u00b1 0.265 ns per loop (mean \u00b1 std. dev. of 7 runs, 10000000 loops each)\n",
+ "\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "some_dict[1] = 1\n",
+ "%timeit some_dict['5']\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "28.5 ns \u00b1 0.142 ns per loop (mean \u00b1 std. dev. of 7 runs, 10000000 loops each)\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "%timeit another_dict['5']\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "Traceback (most recent call last):\n",
+ " File \"\", line 1, in \n",
+ "KeyError: 1\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "another_dict[1] # Trying to access a key that doesn't exist\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "38.5 ns \u00b1 0.0913 ns per loop (mean \u00b1 std. dev. of 7 runs, 10000000 loops each)\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "%timeit another_dict['5']\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\u4e3a\u4ec0\u4e48\u76f8\u540c\u7684\u67e5\u627e\u4f1a\u53d8\u5f97\u8d8a\u6765\u8d8a\u6162\uff1f\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e\n",
+ "+ CPython \u6709\u4e00\u4e2a\u901a\u7528\u7684\u5b57\u5178\u67e5\u627e\u51fd\u6570\uff0c\u53ef\u4ee5\u5904\u7406\u6240\u6709\u7c7b\u578b\u7684\u952e\uff08`str`\u3001`int`\u3001\u4efb\u4f55\u5bf9\u8c61...\uff09\uff0c\u4ee5\u53ca\u4e00\u4e2a\u4e13\u95e8\u7528\u4e8e\u5904\u7406\u4ec5\u7531 `str` \u952e\u7ec4\u6210\u7684\u5b57\u5178\u7684\u5e38\u89c1\u60c5\u51b5\u3002\n",
+ "+ \u4e13\u7528\u51fd\u6570\uff08\u5728 CPython \u7684 [\u6e90](https://github.com/python/cpython/blob/522691c46e2ae51faaad5bbbce7d959dd61770df/Objects/dictobject.c#L841) \u4e2d\u540d\u4e3a `lookdict_unicode`\uff09\u77e5\u9053\u6240\u6709\u73b0\u6709\u7684\u952e\uff08\u5305\u62ec\u67e5\u627e\u7684 key) \u662f\u5b57\u7b26\u4e32\uff0c\u5e76\u4f7f\u7528\u66f4\u5feb\u548c\u66f4\u7b80\u5355\u7684\u5b57\u7b26\u4e32\u6bd4\u8f83\u6765\u6bd4\u8f83\u952e\uff0c\u800c\u4e0d\u662f\u8c03\u7528 `__eq__` \u65b9\u6cd5\u3002\n",
+ "+ \u7b2c\u4e00\u6b21\u4f7f\u7528\u975e `str` \u952e\u8bbf\u95ee `dict` \u5b9e\u4f8b\u65f6\uff0c\u4f1a\u5bf9\u5176\u8fdb\u884c\u4fee\u6539\uff0c\u4ee5\u4fbf\u5c06\u6765\u7684\u67e5\u627e\u4f7f\u7528\u901a\u7528\u51fd\u6570\u3002\n",
+ "+ \u8fd9\u4e2a\u8fc7\u7a0b\u5bf9\u4e8e\u7279\u5b9a\u7684 `dict` \u5b9e\u4f8b\u662f\u4e0d\u53ef\u9006\u7684\uff0c\u5e76\u4e14\u952e\u751a\u81f3\u4e0d\u5fc5\u5b58\u5728\u4e8e\u5b57\u5178\u4e2d\u3002 \u8fd9\u5c31\u662f\u4e3a\u4ec0\u4e48\u5bf9\u4e0d\u5b58\u5728\u7684\u952e\u8fdb\u884c\u67e5\u627e\u5177\u6709\u76f8\u540c\u526f\u4f5c\u7528\u7684\u539f\u56e0\u3002\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Bloating instance `dict`s/\u53d8\u81c3\u80bf\u7684`dict`\u5b9e\u4f8b\u4eec *\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": []
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "import sys\n",
+ "\n",
+ "class SomeClass:\n",
+ " def __init__(self):\n",
+ " self.some_attr1 = 1\n",
+ " self.some_attr2 = 2\n",
+ " self.some_attr3 = 3\n",
+ " self.some_attr4 = 4\n",
+ "\n",
+ "\n",
+ "def dict_size(o):\n",
+ " return sys.getsizeof(o.__dict__)\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output:** (Python 3.8, \u5176\u4ed6 Python 3 \u7684\u7248\u672c\u4e5f\u8bb8\u7a0d\u6709\u4e0d\u540c)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "104\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "o1 = SomeClass()\n",
+ "o2 = SomeClass()\n",
+ "dict_size(o1)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "104\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "dict_size(o2)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "232\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "del o1.some_attr1\n",
+ "o3 = SomeClass()\n",
+ "dict_size(o3)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "232\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "dict_size(o1)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\u8ba9\u6211\u4eec\u5728\u4e00\u4e2a\u65b0\u7684\u89e3\u91ca\u5668\u4e2d\u518d\u8bd5\u4e00\u6b21\uff1a\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "104 # \u610f\u6599\u4e4b\u4e2d\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "o1 = SomeClass()\n",
+ "o2 = SomeClass()\n",
+ "dict_size(o1)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "360\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "o1.some_attr5 = 5\n",
+ "o1.some_attr6 = 6\n",
+ "dict_size(o1)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "272\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "dict_size(o2)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "232\n"
+ ]
+ },
+ "output_type": "execute_result",
+ "metadata": {},
+ "execution_count": null
+ }
+ ],
+ "source": [
+ "o3 = SomeClass()\n",
+ "dict_size(o3)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\u662f\u4ec0\u4e48\u8ba9\u90a3\u4e9b\u5b57\u5178\u53d8\u5f97\u81c3\u80bf\uff1f \u4e3a\u4ec0\u4e48\u65b0\u521b\u5efa\u7684\u5bf9\u8c61\u4e5f\u4f1a\u53d8\u81c3\u80bf\uff1f\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e\n",
+ "+ CPython \u80fd\u591f\u5728\u591a\u4e2a\u5b57\u5178\u4e2d\u91cd\u7528\u76f8\u540c\u7684\u201c\u952e\u201d\u5bf9\u8c61\u3002 \u8fd9\u6dfb\u52a0\u5728 [PEP 412](https://www.python.org/dev/peps/pep-0412/) \u4e2d\uff0c\u76ee\u7684\u662f\u51cf\u5c11\u5185\u5b58\u4f7f\u7528\uff0c\u7279\u522b\u662f\u5728\u5b9e\u4f8b\u5b57\u5178\u4e2d \u2014\u2014 \u952e\uff08\u5b9e\u4f8b\u5c5e\u6027\uff09\u51e0\u4e4e\u5728\u6240\u6709\u5b9e\u4f8b\u90fd\u901a\u7528\u3002\n",
+ "+ \u8fd9\u79cd\u4f18\u5316\u5bf9\u4e8e\u5b9e\u4f8b\u5b57\u5178\u6765\u8bf4\u662f\u5341\u5206\u81ea\u7136\u7684\uff0c\u4f46\u5982\u679c\u67d0\u4e9b\u5047\u8bbe\u88ab\u6253\u7834\uff0c\u5b83\u5c31\u4f1a\u88ab\u7981\u7528\u3002\n",
+ "+ \u5bc6\u94a5\u5171\u4eab\u5b57\u5178\u4e0d\u652f\u6301\u5220\u9664\uff1b\u5982\u679c\u5220\u9664\u4e86\u5b9e\u4f8b\u5c5e\u6027\uff0c\u5219\u5b57\u5178\u662f\u201c\u672a\u5171\u4eab\u7684\u201d\uff0c\u5e76\u4e14\u540c\u4e00\u7c7b\u7684\u6240\u6709\u672a\u6765\u5b9e\u4f8b\u90fd\u7981\u7528\u5bc6\u94a5\u5171\u4eab\u3002\n",
+ "+ \u53e6\u5916\uff0c\u5982\u679c\u5b57\u5178\u952e\u5df2\u88ab\u8c03\u6574\u5927\u5c0f\uff08\u56e0\u4e3a\u63d2\u5165\u4e86\u65b0\u952e\uff09\uff0c\u5b83\u4eec\u4fdd\u6301\u5171\u4eab*\u4ec5\u5f53*\u5b83\u4eec\u88ab\u4e00\u4e2a\u5b8c\u5168\u5355\u4e00\u7684\u5b57\u5178\u4f7f\u7528\u65f6\uff08\u8fd9\u5141\u8bb8\u5728\u7b2c\u4e00\u4e2a\u521b\u5efa\u7684\u5b9e\u4f8b\u7684 `__init__` \u4e2d\u6dfb\u52a0\u8bb8\u591a\u5c5e\u6027\uff0c\u800c\u4e0d\u4f1a\u5bfc\u81f4\u201c\u53d6\u6d88\u5171\u4eab\u201d\uff09\u3002\u5982\u679c\u53d1\u751f\u8c03\u6574\u5927\u5c0f\u65f6\u5b58\u5728\u591a\u4e2a\u5b9e\u4f8b\uff0c\u5219\u4e3a\u540c\u4e00\u7c7b\u7684\u6240\u6709\u672a\u6765\u5b9e\u4f8b\u7981\u7528\u5bc6\u94a5\u5171\u4eab\uff1aCPython \u65e0\u6cd5\u5224\u65ad\u60a8\u7684\u5b9e\u4f8b\u662f\u5426\u6b63\u5728\u4f7f\u7528\u76f8\u540c\u7684\u5c5e\u6027\u96c6\uff0c\u5e76\u51b3\u5b9a\u653e\u5f03\u5c1d\u8bd5\u5171\u4eab\u5b83\u4eec\u7684\u952e\u503c\u3002\n",
+ "+ \u4e00\u4e2a\u5c0f\u63d0\u793a\uff0c\u5982\u679c\u4f60\u7684\u76ee\u6807\u662f\u964d\u4f4e\u7a0b\u5e8f\u7684\u5185\u5b58\u5360\u7528\uff1a\u4e0d\u8981\u5220\u9664\u5b9e\u4f8b\u5c5e\u6027\uff0c\u5e76\u786e\u4fdd\u5728 `__init__` \u4e2d\u521d\u59cb\u5316\u6240\u6709\u7684\u5c5e\u6027\uff01\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Minor Ones/\u5c0f\u77e5\u8bc6\u70b9\n",
+ "* `join()` \u662f\u4e00\u4e2a\u5b57\u7b26\u4e32\u64cd\u4f5c\u800c\u4e0d\u662f\u5217\u8868\u64cd\u4f5c. (\u7b2c\u4e00\u6b21\u63a5\u89e6\u4f1a\u89c9\u5f97\u6709\u70b9\u8fdd\u53cd\u76f4\u89c9)\n",
+ "\n",
+ " **\ud83d\udca1 \u8bf4\u660e:**\n",
+ " \u5982\u679c `join()` \u662f\u5b57\u7b26\u4e32\u65b9\u6cd5 \u90a3\u4e48\u5b83\u5c31\u53ef\u4ee5\u5904\u7406\u4efb\u4f55\u53ef\u8fed\u4ee3\u7684\u5bf9\u8c61(\u5217\u8868\uff0c\u5143\u7ec4\uff0c\u8fed\u4ee3\u5668). \u5982\u679c\u5b83\u662f\u5217\u8868\u65b9\u6cd5, \u5219\u5fc5\u987b\u5728\u6bcf\u79cd\u7c7b\u578b\u4e2d\u5355\u72ec\u5b9e\u73b0. \u53e6\u5916, \u5728 `list` \u5bf9\u8c61\u7684\u901a\u7528API\u4e2d\u5b9e\u73b0\u4e00\u4e2a\u4e13\u7528\u4e8e\u5b57\u7b26\u4e32\u7684\u65b9\u6cd5\u6ca1\u6709\u592a\u5927\u7684\u610f\u4e49.\n",
+ "\n",
+ "* \u770b\u7740\u5947\u602a\u4f46\u80fd\u6b63\u786e\u8fd0\u884c\u7684\u8bed\u53e5:\n",
+ " + `[] = ()` \u8bed\u53e5\u5728\u8bed\u4e49\u4e0a\u662f\u6b63\u786e\u7684 (\u89e3\u5305\u4e00\u4e2a\u7a7a\u7684 `tuple` \u5e76\u8d4b\u503c\u7ed9 `list`)\n",
+ " + `'a'[0][0][0][0][0]` \u5728\u8bed\u4e49\u4e0a\u4e5f\u662f\u6b63\u786e\u7684, \u56e0\u4e3a\u5728 Python \u4e2d\u5b57\u7b26\u4e32\u540c\u65f6\u4e5f\u662f[\u5e8f\u5217](https://docs.python.org/3/glossary.html#term-sequence)(\u53ef\u8fed\u4ee3\u5bf9\u8c61\u652f\u6301\u4f7f\u7528\u6574\u6570\u7d22\u5f15\u8bbf\u95ee\u5143\u7d20).\n",
+ " + `3 --0-- 5 == 8` \u548c `--5 == 5` \u5728\u8bed\u4e49\u4e0a\u90fd\u662f\u6b63\u786e\u7684, \u4e14\u7ed3\u679c\u7b49\u4e8e `True`.(\u8bd1: 3\u51cf\u8d1f0\u7b49\u4e8e3\uff0c\u518d\u51cf\u8d1f5\u76f8\u5f53\u4e8e\u52a05\u7b49\u4e8e8\uff1b\u8d1f\u7684\u8d1f5\u7b49\u4e8e5.)\n",
+ "\n",
+ "* \u9274\u4e8e `a` \u662f\u4e00\u4e2a\u6570\u5b57, `++a` \u548c `--a` \u90fd\u662f\u6709\u6548\u7684 Python \u8bed\u53e5, \u4f46\u5176\u6548\u679c\u4e0e C, C++ \u6216 Java \u7b49\u4e0d\u4e00\u6837.\n",
+ " ```py\n",
+ " >>> a = 5\n",
+ " >>> a\n",
+ " 5\n",
+ " >>> ++a\n",
+ " 5\n",
+ " >>> --a\n",
+ " 5\n",
+ " ```\n",
+ "\n",
+ " **\ud83d\udca1 \u8bf4\u660e:**\n",
+ " + python \u91cc\u6ca1\u6709 `++` \u64cd\u4f5c\u7b26. \u8fd9\u5176\u5b9e\u662f\u4e24\u4e2a `+` \u64cd\u4f5c\u7b26.\n",
+ " + `++a` \u88ab\u89e3\u6790\u4e3a `+(+a)` \u6700\u540e\u7b49\u4e8e `a`. `--a` \u540c\u7406.\n",
+ " + \u8fd9\u4e2a StackOverflow [\u56de\u7b54](https://stackoverflow.com/questions/3654830/why-are-there-no-and-operators-in-python) \u8ba8\u8bba\u4e86\u4e3a\u4ec0\u4e48 Python \u4e2d\u7f3a\u5c11\u589e\u91cf\u548c\u51cf\u91cf\u8fd0\u7b97\u7b26.\n",
+ "\n",
+ "* Python \u4f7f\u7528 2\u4e2a\u5b57\u8282\u5b58\u50a8\u51fd\u6570\u4e2d\u7684\u672c\u5730\u53d8\u91cf. \u7406\u8bba\u4e0a, \u8fd9\u610f\u5473\u7740\u51fd\u6570\u4e2d\u53ea\u80fd\u5b9a\u4e4965536\u4e2a\u53d8\u91cf. \u4f46\u662f\uff0cPython \u5185\u7f6e\u4e86\u4e00\u4e2a\u65b9\u4fbf\u7684\u89e3\u51b3\u65b9\u6848\uff0c\u53ef\u7528\u4e8e\u5b58\u50a8\u8d85\u8fc72^16\u4e2a\u53d8\u91cf\u540d. \u4e0b\u9762\u7684\u4ee3\u7801\u6f14\u793a\u4e86\u5f53\u5b9a\u4e49\u4e86\u8d85\u8fc765536\u4e2a\u5c40\u90e8\u53d8\u91cf\u65f6\u5806\u6808\u4e2d\u53d1\u751f\u7684\u60c5\u51b5 (\u8b66\u544a: \u8fd9\u6bb5\u4ee3\u7801\u4f1a\u6253\u5370\u5927\u7ea62^18\u884c\u6587\u672c, \u8bf7\u505a\u597d\u51c6\u5907!):\n",
+ " ```py\n",
+ " import dis\n",
+ " exec(\"\"\"\n",
+ " def f():\n",
+ " \"\"\" + \"\"\"\n",
+ " \"\"\".join([\"X\"+str(x)+\"=\" + str(x) for x in range(65539)]))\n",
+ "\n",
+ " f()\n",
+ "\n",
+ " print(dis.dis(f))\n",
+ " ```\n",
+ "\n",
+ "* \u4f60\u7684 *Python \u4ee3\u7801* \u5e76\u4e0d\u4f1a\u591a\u7ebf\u7a0b\u540c\u65f6\u8fd0\u884c (\u662f\u7684, \u4f60\u6ca1\u542c\u9519!). \u867d\u7136\u4f60\u89c9\u5f97\u4f1a\u4ea7\u751f\u591a\u4e2a\u7ebf\u7a0b\u5e76\u8ba9\u5b83\u4eec\u540c\u65f6\u6267\u884c\u4f60\u7684\u4ee3\u7801, \u4f46\u662f, \u7531\u4e8e [\u5168\u5c40\u89e3\u91ca\u9501](https://wiki.python.org/moin/GlobalInterpreterLock)\u7684\u5b58\u5728, \u4f60\u6240\u505a\u7684\u53ea\u662f\u8ba9\u4f60\u7684\u7ebf\u7a0b\u4f9d\u6b21\u5728\u540c\u4e00\u4e2a\u6838\u5fc3\u4e0a\u6267\u884c. Python \u591a\u7ebf\u7a0b\u9002\u7528\u4e8eIO\u5bc6\u96c6\u578b\u7684\u4efb\u52a1, \u4f46\u5982\u679c\u60f3\u8981\u5e76\u884c\u5904\u7406CPU\u5bc6\u96c6\u578b\u7684\u4efb\u52a1, \u4f60\u5e94\u8be5\u4f1a\u60f3\u4f7f\u7528 [multiprocessing](https://docs.python.org/2/library/multiprocessing.html) \u6a21\u5757.\n",
+ "\n",
+ "* \u5217\u8868\u5207\u7247\u8d85\u51fa\u7d22\u5f15\u8fb9\u754c\u800c\u4e0d\u5f15\u53d1\u4efb\u4f55\u9519\u8bef\n",
+ " ```py\n",
+ " >>> some_list = [1, 2, 3, 4, 5]\n",
+ " >>> some_list[111:]\n",
+ " []\n",
+ " ```\n",
+ "\n",
+ "* `int('\u0661\u0662\u0663\u0664\u0665\u0666\u0667\u0668\u0669')` \u5728 Python 3 \u4e2d\u4f1a\u8fd4\u56de `123456789`. \u5728 Python \u4e2d, \u5341\u8fdb\u5236\u5b57\u7b26\u5305\u62ec\u6570\u5b57\u5b57\u7b26, \u4ee5\u53ca\u53ef\u7528\u4e8e\u5f62\u6210\u5341\u8fdb\u5236\u6570\u5b57\u7684\u6240\u6709\u5b57\u7b26, \u4f8b\u5982: U+0660, ARABIC-INDIC DIGIT ZERO. \u8fd9\u6709\u4e00\u4e2a\u5173\u4e8e\u6b64\u7684 [\u6709\u8da3\u6545\u4e8b](http://chris.improbable.org/2014/8/25/adventures-in-unicode-digits/).\n",
+ "\n",
+ "* `'abc'.count('') == 4`. \u8fd9\u6709\u4e00\u4e2a `count` \u65b9\u6cd5\u7684\u76f8\u8fd1\u5b9e\u73b0, \u80fd\u66f4\u597d\u7684\u8bf4\u660e\u95ee\u9898\n",
+ " ```py\n",
+ " def count(s, sub):\n",
+ " result = 0\n",
+ " for i in range(len(s) + 1 - len(sub)):\n",
+ " result += (s[i:i + len(sub)] == sub)\n",
+ " return result\n",
+ " ```\n",
+ " \u8fd9\u4e2a\u884c\u4e3a\u662f\u7531\u4e8e\u7a7a\u5b50\u4e32(`''`)\u4e0e\u539f\u59cb\u5b57\u7b26\u4e32\u4e2d\u957f\u5ea6\u4e3a0\u7684\u5207\u7247\u76f8\u5339\u914d\u5bfc\u81f4\u7684.\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > First things first!/\u8981\u4e8b\u4f18\u5148 *\n",
+ "\u4f17\u6240\u5468\u77e5\uff0cPython 3.8 \u63a8\u51fa\"\u6d77\u8c61\"\u8fd0\u7b97\u7b26 (`:=`) \u65b9\u4fbf\u6613\u7528\uff0c\u8ba9\u6211\u4eec\u4e00\u8d77\u770b\u770b\u3002\n",
+ "\n",
+ "1\\.\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "```py\n",
+ "# Python \u7248\u672c 3.8+\n",
+ "\n",
+ ">>> a = \"wtf_walrus\"\n",
+ ">>> a\n",
+ "```\n",
+ "```py\n",
+ "'wtf_walrus'\n",
+ "\n",
+ "```\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "```py\n",
+ ">>> a := \"wtf_walrus\"\n",
+ "```\n",
+ "```py\n",
+ "File \"\", line 1\n",
+ " a := \"wtf_walrus\"\n",
+ " ^\n",
+ "SyntaxError: invalid syntax\n",
+ "\n",
+ "```\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "```py\n",
+ ">>> (a := \"wtf_walrus\") # \u8be5\u8bed\u53e5\u6709\u6548\n",
+ "```\n",
+ "```py\n",
+ "'wtf_walrus'\n",
+ "```\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "```py\n",
+ ">>> a\n",
+ "```\n",
+ "```py\n",
+ "'wtf_walrus'\n",
+ "```\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "2 \\.\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "```py\n",
+ "# Python \u7248\u672c 3.8+\n",
+ "\n",
+ ">>> a = 6, 9\n",
+ ">>> a\n",
+ "```\n",
+ "```py\n",
+ "(6, 9)\n",
+ "\n",
+ "```\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "```py\n",
+ ">>> (a := 6, 9)\n",
+ "```\n",
+ "```py\n",
+ "(6, 9)\n",
+ "```\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "```py\n",
+ ">>> a\n",
+ "```\n",
+ "```py\n",
+ "6\n",
+ "\n",
+ "```\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "```py\n",
+ ">>> a, b = 6, 9 # \u5178\u578b\u62c6\u5305\u64cd\u4f5c\n",
+ ">>> a, b\n",
+ "```\n",
+ "```py\n",
+ "(6, 9)\n",
+ "```\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "```py\n",
+ ">>> (a, b = 16, 19) # \u51fa\u9519\u5566\n",
+ "```\n",
+ "```py\n",
+ " File \"\", line 1\n",
+ " (a, b = 16, 19)\n",
+ " ^\n",
+ "SyntaxError: invalid syntax\n",
+ "\n",
+ "```\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "```py\n",
+ ">>> (a, b := 16, 19) # \u8fd9\u91cc\u7684\u7ed3\u679c\u662f\u4e00\u4e2a\u5947\u602a\u7684\u4e09\u5143\u7ec4\n",
+ "```\n",
+ "```py\n",
+ "(6, 16, 19)\n",
+ "\n",
+ "```\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "```py\n",
+ ">>> a # a\u503c\u4ecd\u7136\u6ca1\u53d8?\n",
+ "```\n",
+ "```py\n",
+ "6\n",
+ "\n",
+ "```\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "```py\n",
+ ">>> b\n",
+ "```\n",
+ "```py\n",
+ "16\n",
+ "```\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e\n",
+ "\n",
+ "**\u201c\u6d77\u8c61\u201d\u8fd0\u7b97\u7b26\u7b80\u4ecb**\n",
+ "\n",
+ "\u6d77\u8c61\u8fd0\u7b97\u7b26 (`:=`) \u5728Python 3.8\u4e2d\u88ab\u5f15\u5165\uff0c\u7528\u6765\u5728\u8868\u8fbe\u5f0f\u4e2d\u4e3a\u53d8\u91cf\u8d4b\u503c\u3002\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "```py\n",
+ "def some_func():\n",
+ " # \u5047\u8bbe\u8fd9\u513f\u6709\u4e00\u4e9b\u8017\u65f6\u7684\u8ba1\u7b97\n",
+ " # time.sleep(1000)\n",
+ " return 5\n",
+ "\n",
+ "# \u5f15\u5165\u201c\u6d77\u8c61\u201d\u8fd0\u7b97\u7b26\u524d\u7684\u4f8b\u5b50\n",
+ "if some_func():\n",
+ " print(some_func()) # \u7cdf\u7cd5\u7684\u6848\u4f8b\u2014\u2014\u51fd\u6570\u8fd0\u7b97\u4e86\u4e24\u6b21\n",
+ "\n",
+ "# \u6216\u8005\uff0c\u52a0\u4ee5\u6539\u8fdb\uff1a\n",
+ "a = some_func()\n",
+ "if a:\n",
+ " print(a)\n",
+ "\n",
+ "# \u6709\u4e86\u201c\u6d77\u8c61\u201d\u8fd0\u7b97\u7b26\uff0c\u4f60\u53ef\u4ee5\u5199\u7684\u66f4\u7b80\u6d01\uff1a\n",
+ "if a := some_func():\n",
+ " print(a)\n",
+ "```\n",
+ "```py\n",
+ "```\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**\u8f93\u51fa (> Python 3.8):**\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "```py\n",
+ "5\n",
+ "5\n",
+ "5\n",
+ "```\n",
+ "```py\n",
+ "```\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\u8fd9\u6837\u65e2\u51cf\u5c11\u4e86\u4e00\u884c\u4ee3\u7801\uff0c\u53c8\u907f\u514d\u4e86\u4e24\u6b21\u8c03\u7528 `some_func` \u51fd\u6570\u3002\n",
+ "\n",
+ "- \u5728\u9876\u5c42\u7684\u65e0\u62ec\u53f7\u8d4b\u503c\u64cd\u4f5c\uff08\u4f7f\u7528\u201c\u6d77\u8c61\u201d\u8fd0\u7b97\u7b26\uff09\u88ab\u9650\u5236\uff0c\u56e0\u6b64\u4f8b1\u4e2d\u7684 `a := \"wtf_walrus\"` \u51fa\u73b0\u4e86 `SyntaxError` \u3002\u7528\u62ec\u53f7\u62ec\u8d77\u6765\u3002\u5b83\u5c31\u80fd\u6b63\u5e38\u5de5\u4f5c\u4e86\u3002\n",
+ "\n",
+ "- \u4e00\u822c\u7684\uff0c\u5305\u542b `=` \u64cd\u4f5c\u7684\u8868\u8fbe\u5f0f\u662f\u4e0d\u80fd\u7528\u62ec\u53f7\u62ec\u8d77\u6765\u7684\uff0c\u56e0\u6b64 `(a, b = 6, 9)` \u4e2d\u51fa\u73b0\u4e86\u8bed\u6cd5\u9519\u8bef\u3002\n",
+ "\n",
+ "- \u201c\u6d77\u8c61\u201d\u8fd0\u7b97\u7b26\u7684\u8bed\u6cd5\u5f62\u5f0f\u4e3a\uff1a`NAME:= expr`\uff0c`NAME` \u662f\u4e00\u4e2a\u6709\u6548\u7684\u6807\u8bc6\u7b26\uff0c\u800c `expr` \u662f\u4e00\u4e2a\u6709\u6548\u7684\u8868\u8fbe\u5f0f\u3002 \u56e0\u6b64\uff0c\u8fd9\u610f\u5473\u7740\u5b83\u4e0d\u652f\u6301\u53ef\u8fed\u4ee3\u7684\u6253\u5305\u548c\u62c6\u5305\u3002\n",
+ "\n",
+ " - `(a := 6, 9)` \u7b49\u4ef7\u4e8e `((a := 6), 9)` \uff0c\u6700\u7ec8\u5f97\u5230 `(a, 9) ` (\u5176\u4e2d `a` \u7684\u503c\u4e3a6)\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "```py\n",
+ " >>> (a := 6, 9) == ((a := 6), 9)\n",
+ "```\n",
+ "```py\n",
+ " True\n",
+ "```\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "```py\n",
+ " >>> x = (a := 696, 9)\n",
+ " >>> x\n",
+ "```\n",
+ "```py\n",
+ " (696, 9)\n",
+ "```\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "```py\n",
+ " >>> x[0] is a # \u4e24\u4e2a\u53d8\u91cf\u6307\u5411\u540c\u4e00\u5185\u5b58\u7a7a\u95f4\n",
+ "```\n",
+ "```py\n",
+ " True\n",
+ "```\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ " - \u7c7b\u4f3c\u7684\uff0c `(a, b := 16, 19)` \u7b49\u4ef7\u4e8e `(a, (b := 16), 19)` \uff0c\u53ea\u662f\u4e00\u4e2a\u4e09\u5143\u7ec4\u3002 \n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### > Wild imports/\u901a\u914d\u7b26\u5bfc\u5165\u65b9\u5f0f *\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "```py\n",
+ "# File: module.py\n",
+ "\n",
+ "def some_weird_name_func_():\n",
+ " print(\"works!\")\n",
+ "\n",
+ "def _another_weird_name_func():\n",
+ " print(\"works!\")\n",
+ "\n",
+ "```\n",
+ "```py\n",
+ "```\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "**Output**\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "```py\n",
+ ">>> from module import *\n",
+ ">>> some_weird_name_func_()\n",
+ "```\n",
+ "```py\n",
+ "\"works!\"\n",
+ "```\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "```py\n",
+ ">>> _another_weird_name_func()\n",
+ "```\n",
+ "```py\n",
+ "Traceback (most recent call last):\n",
+ " File \"\", line 1, in \n",
+ "NameError: name '_another_weird_name_func' is not defined\n",
+ "```\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### \ud83d\udca1 \u8bf4\u660e\n",
+ "\n",
+ "- \u901a\u5e38\u5efa\u8bae\u4e0d\u8981\u4f7f\u7528\u901a\u914d\u7b26\u5bfc\u5165\u3002\u7b2c\u4e00\u4e2a\u660e\u663e\u7684\u539f\u56e0\u662f\uff0c\u5728\u901a\u914d\u7b26\u5bfc\u5165\u4e2d\uff0c\u5e26\u6709\u524d\u5bfc\u4e0b\u5212\u7ebf\u7684\u540d\u79f0\u4e0d\u4f1a\u88ab\u5bfc\u5165\u3002\u8fd9\u53ef\u80fd\u4f1a\u5bfc\u81f4\u8fd0\u884c\u65f6\u51fa\u9519\u3002\n",
+ "- \u5982\u679c\u6211\u4eec\u4f7f\u7528 `from ... import a, b, c` \u8bed\u6cd5\uff0c\u4e0a\u9762\u7684 `NameError` \u5c31\u4e0d\u4f1a\u53d1\u751f\u3002\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "```py\n",
+ " >>> from module import some_weird_name_func_, _another_weird_name_func\n",
+ " >>> _another_weird_name_func()\n",
+ "```\n",
+ "```py\n",
+ " works!\n",
+ "```\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "- \u5982\u679c\u4f60\u771f\u7684\u60f3\u4f7f\u7528\u901a\u914d\u7b26\u5bfc\u5165\uff0c\u90a3\u4e48\u4f60\u5fc5\u987b\u5728\u4f60\u7684\u6a21\u5757\u4e2d\u5b9a\u4e49\u5217\u8868`__all__`\uff0c\u5b83\u5305\u542b\u4e00\u7cfb\u5217\u516c\u5171\u5bf9\u8c61\uff0c\u5f53\u6211\u4eec\u8fdb\u884c\u901a\u914d\u7b26\u5bfc\u5165\u65f6\uff0c\u5217\u8868\u4e2d\u7684\u8fd9\u4e9b\u5bf9\u8c61\u5c06\u88ab\u5bfc\u5165\u3002\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "```py\n",
+ " __all__ = ['_another_weird_name_func']\n",
+ "\n",
+ " def some_weird_name_func_():\n",
+ " print(\"works!\")\n",
+ "\n",
+ " def _another_weird_name_func():\n",
+ " print(\"works!\")\n",
+ "```\n",
+ "```py\n",
+ "```\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ " **Output**\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "```py\n",
+ " >>> _another_weird_name_func()\n",
+ "```\n",
+ "```py\n",
+ " \"works!\"\n",
+ "```\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "```py\n",
+ " >>> some_weird_name_func_()\n",
+ "```\n",
+ "```py\n",
+ " Traceback (most recent call last):\n",
+ " File \"\", line 1, in \n",
+ " NameError: name 'some_weird_name_func_' is not defined\n",
+ "```\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Contributing/\u8d21\u732e\n",
+ "\n",
+ "\u6b22\u8fce\u5404\u79cd\u8865\u4e01! \u8be6\u60c5\u8bf7\u770b[CONTRIBUTING.md](https://github.com/satwikkansal/wtfpython/blob/master/CONTRIBUTING.md).(\u8bd1: \u8fd9\u662f\u7ed9\u539f\u5e93\u63d0\u8d21\u732e\u7684\u8981\u6c42\u6a21\u7248)\n",
+ "\n",
+ "\u4f60\u53ef\u4ee5\u901a\u8fc7\u65b0\u5efa [issue](https://github.com/satwikkansal/wtfpython/issues/new) \u6216\u8005\u5728\u4e0a [Gitter](https://gitter.im/wtfpython/Lobby) \u4e0e\u6211\u4eec\u8fdb\u884c\u8ba8\u8bba.\n",
+ "\n",
+ "(\u8bd1: \u5982\u679c\u4f60\u60f3\u5bf9\u8fd9\u4e2a\u7ffb\u8bd1\u9879\u76ee\u63d0\u4f9b\u5e2e\u52a9, \u8bf7\u770b[\u8fd9\u91cc](https://github.com/leisurelicht/wtfpython-cn/blob/master/CONTRIBUTING.md))\n",
+ "\n",
+ "# Acknowledgements/\u81f4\u8c22\n",
+ "\n",
+ "\u8fd9\u4e2a\u7cfb\u5217\u6700\u521d\u7684\u60f3\u6cd5\u548c\u8bbe\u8ba1\u7075\u611f\u6765\u81ea\u4e8e Denys Dovhan \u7684\u9879\u76ee [wtfjs](https://github.com/denysdovhan/wtfjs). \u793e\u533a\u7684\u5f3a\u5927\u652f\u6301\u8ba9\u5b83\u6210\u957f\u4e3a\u73b0\u5728\u7684\u6a21\u6837.\n",
+ "\n",
+ "#### Some nice Links!/\u4e00\u4e9b\u4e0d\u9519\u7684\u8d44\u6e90\n",
+ "* https://www.youtube.com/watch?v=sH4XF6pKKmk\n",
+ "* https://www.reddit.com/r/Python/comments/3cu6ej/what_are_some_wtf_things_about_python\n",
+ "* https://sopython.com/wiki/Common_Gotchas_In_Python\n",
+ "* https://stackoverflow.com/questions/530530/python-2-x-gotchas-and-landmines\n",
+ "* https://stackoverflow.com/questions/1011431/common-pitfalls-in-python\n",
+ "* https://www.python.org/doc/humor/\n",
+ "* https://www.codementor.io/satwikkansal/python-practices-for-efficient-code-performance-memory-and-usability-aze6oiq65\n",
+ "\n",
+ "# \ud83c\udf93 License/\u8bb8\u53ef\n",
+ "\n",
+ "[![CC 4.0][license-image]][license-url]\n",
+ "\n",
+ "© [Satwik Kansal](https://satwikkansal.xyz)\n",
+ "\n",
+ "[license-url]: http://www.wtfpl.net\n",
+ "[license-image]: https://img.shields.io/badge/License-WTFPL%202.0-lightgrey.svg?style=flat-square\n",
+ "\n"
+ ]
+ }
+ ],
+ "metadata": {},
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
\ No newline at end of file