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