{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "
一些有趣且鲜为人知的 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", "