From 1ccca4113bc9b7383ae0044b40b80e46b53750a8 Mon Sep 17 00:00:00 2001 From: Lanxin <675579465@qq.com> Date: 2019年9月27日 13:45:41 +0800 Subject: [PATCH 1/7] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=A8=A1=E5=9D=97?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E7=BC=96=E5=86=99=E5=9F=BA=E7=A1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...345206円231円345円237円272円347円241円200円.ipynb" | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git "a/Learning Python/5343円200円201円346円250円241円345円235円227円345円222円214円345円214円205円/2. 346円250円241円345円235円227円344円273円243円347円240円201円347円274円226円345円206円231円345円237円272円347円241円200円.ipynb" "b/Learning Python/5343円200円201円346円250円241円345円235円227円345円222円214円345円214円205円/2. 346円250円241円345円235円227円344円273円243円347円240円201円347円274円226円345円206円231円345円237円272円347円241円200円.ipynb" index 12dcb0c..5fa4477 100644 --- "a/Learning Python/5343円200円201円346円250円241円345円235円227円345円222円214円345円214円205円/2. 346円250円241円345円235円227円344円273円243円347円240円201円347円274円226円345円206円231円345円237円272円347円241円200円.ipynb" +++ "b/Learning Python/5343円200円201円346円250円241円345円235円227円345円222円214円345円214円205円/2. 346円250円241円345円235円227円344円273円243円347円240円201円347円274円226円345円206円231円345円237円272円347円241円200円.ipynb" @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 模块的创建 \n", + "# 1. 模块的创建 \n", "定义模块,只要使用文本编辑器,把一些 Python 代码输入至文本文件中,然后以".py"为后缀名进行保存,任何此类文件都会被自动认为是 Python 模块。在模块顶层指定的所有变量名都会变成其属性,并且可以导出供客户端来使用。 \n", "\n", "例如,如果在名为 module1.py 的文件中输入下面的 def 语句,并将这个文件导入,就会创建一个拥有一个属性的模块对象。" @@ -24,13 +24,13 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 模块文件名 \n", + "## 1.1 模块文件名 \n", "模块名在 Python 程序中会变成变量名(没有.py)。当一个模块被导入时,Python 会把内部模块名映射到外部文件名,也就是说通过把模块搜索路径中的目录路径加在前边,而 .py 或其他后缀名添加在后边。 \n", "\n", - "# 模块的使用 \n", + "# 2. 模块的使用 \n", "客户端可以执行 import 或 from 语句。import 会读取整个模块,所以必须进行定义后才能读取它的变量名;from 将获取(或者说复制)模块特定的变量名。 \n", "\n", - "## import 语句 \n", + "## 2.1 import 语句 \n", "上面的变量名 module1 有两个不同的目的:识别要被载入的外部文件,同时会生成脚本中的变量,在文件加载后,用来引用模块对象。" ] }, @@ -63,7 +63,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## from 语句 \n", + "## 2.2 from 语句 \n", "因为 from 会把变量名复制到另一个作用域,所以它就可以让我们直接在脚本中使用复制后的变量名,而不需要通过模块。" ] }, @@ -89,7 +89,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## from * 语句 \n", + "## 2.3 from * 语句 \n", "当我们使用 * 时,会取得模块顶层所有赋了值的变量名的拷贝。还是在脚本中使用复制后得到的变量名 printer,而不需要通过模块名。" ] }, @@ -115,7 +115,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 导入只发生一次 \n", + "## 2.4 导入只发生一次 \n", "模块会在第一次 import 或 from 时载入并执行,并且只在第一次如此。之后的导入操作都只会取出已加载的模块对象。 \n", "\n", "**初始化代码**" @@ -182,7 +182,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## import 和 from 是赋值语句 \n", + "## 2.5 import 和 from 是赋值语句 \n", "import 和 from 是可执行的语句,可以嵌套在 if 测试中,出现在函数 def、try 语句之中等。 \n", "\n", "import 和 from 都是隐形的赋值语句:\n", @@ -194,7 +194,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## import 和 from 的对等性 \n", + "## 2.6 import 和 from 的对等性 \n", "一个像这样的 from 语句:\n", "```\n", "from module import name1, name2\n", @@ -212,14 +212,14 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 模块命名空间 \n", - "## 文件生成命名空间 \n", + "# 3. 模块命名空间 \n", + "## 3.1 文件生成命名空间 \n", "- **模块语句会在首次导入时执行。**\n", "- **顶层的赋值语句会创建模块属性。**\n", "- **模块的命名空间能通过属性 `__dict__` 或 dir(M) 获取。**\n", "- **模块是一个独立的作用域(本地变量就是全局变量)。**\n", "\n", - "## 命名空间字典:`__dict__` \n", + "## 3.2 命名空间字典:`__dict__` \n", "在内部模块命名空间是作为字典对象进行存储的。可以通过模块的 `__dict__` 属性获取模块命名空间字典:" ] }, @@ -255,7 +255,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 属性名的点号运算 \n", + "## 3.3 属性名的点号运算 \n", "在 Python 中,可以使用点号运算语法 object.attribute 获取任意 object 的 attribute 属性。 \n", "\n", "属性的点号运算与作用域法则无关,LEGB 规则只适用于无点号运算的纯变量名。以下是其规则:\n", @@ -264,7 +264,7 @@ "- **多层点号运算。**X.Y.Z 指的是寻找对象 X 之中的变量名 Y,然后再找对象 X.Y 之中的 Z。\n", "- **通用性。**点号运算可用于任何具有属性的对象:模块、类、C 扩展类型等。\n", "\n", - "## 导入和作用域 \n", + "## 3.4 导入和作用域 \n", "导入操作不会赋予被导入文件中的代码对上层代码的可见度:被导入文件无法看见进行导入的文件内的变量名。更确切的说法是:\n", "- 函数绝对无法看见其他函数内的变量名,除非它们从物理上处于这个函数内。\n", "- 模块程序代码绝对无法看见其他模块内的变量名,除非明确地进行了导入。\n", @@ -276,14 +276,14 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 重载模块 \n", + "# 4. 重载模块 \n", "调用 reload 内置函数可以强制使模块代码重新载入并重新运行。此文件中新的代码的赋值语句会在适当的地方修改现有的模块对象。 \n", "\n", "reload 函数可以修改程序的一些部分,而无需停止整个程序。因此,利用 reload,可以立即看到对组件的修改的效果。 \n", "\n", "在 Python 3.X 中,reload 在 imp 标准库模块中,需要 import 语句或 from 语句来载入该工具。 \n", "\n", - "## reload 基础 \n", + "## 4.1 reload 基础 \n", "- reload 是 Python 中的内置函数,而不是语句。\n", "- 传给 reload 的是已经存在的模块对象,而不是变量名。\n", "- reload 在 Python 3.X 中位于模块中,并且必须导入自己。\n", @@ -305,7 +305,7 @@ "- **重载只会对以后使用 from 的客户端造成影响。**\n", "- **重载只应用于单个模块。** \n", "\n", - "## reload 实例 \n", + "## 4.2 reload 实例 \n", "下面,我们要修改并重载一个模块文件,但不会中止交互模式的 Python 会话。 \n", "\n", "首先,在文本编辑器中,编写一个名为 changer.py 的模块文件,其内容如下:" @@ -445,7 +445,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.5" + "version": "3.6.8" } }, "nbformat": 4, From 775d6b584d1392ac5157c554f265cb769702347b Mon Sep 17 00:00:00 2001 From: Lanxin <675579465@qq.com> Date: 2019年9月27日 13:49:00 +0800 Subject: [PATCH 2/7] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=A8=A1=E5=9D=97?= =?UTF-8?q?=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...346250円241円345円235円227円345円214円205円.ipynb" | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git "a/Learning Python/5343円200円201円346円250円241円345円235円227円345円222円214円345円214円205円/3. 346円250円241円345円235円227円345円214円205円.ipynb" "b/Learning Python/5343円200円201円346円250円241円345円235円227円345円222円214円345円214円205円/3. 346円250円241円345円235円227円345円214円205円.ipynb" index de3c67f..6ba2a5a 100644 --- "a/Learning Python/5343円200円201円346円250円241円345円235円227円345円222円214円345円214円205円/3. 346円250円241円345円235円227円345円214円205円.ipynb" +++ "b/Learning Python/5343円200円201円346円250円241円345円235円227円345円222円214円345円214円205円/3. 346円250円241円345円235円227円345円214円205円.ipynb" @@ -6,19 +6,19 @@ "source": [ "除了模块名之外,导入也可以指定目录路径。Python 代码的目录就称为包,因此,这类导入就称为包导入。 \n", "\n", - "# 包导入基础 \n", + "# 1. 包导入基础 \n", "在 import 语句中可以列出路径名称,彼此以点号相隔。 \n", "```\n", "import dir1.dir2.mod\n", "```\n", "通过这个路径可以获得 dir1 目录中的 dir2 目录中的 mod.py 模块文件。 \n", "\n", - "## 包和搜索路径设置 \n", + "## 1.1 包和搜索路径设置 \n", "import 语句中的目录路径只能是以点号间隔的变量。不能在 import 语句中使用任何平台特定的路径语法。需要在模块搜索路径设置中使用平台特定的语法,来定义容器的目录。 \n", "\n", "如果完整路径是 `C:\\mycode\\dir1\\dir2\\mod.py`,则可以增加 `C:\\mycode` 在 PYTHONPATH 系统变量中或是 .pth 文件中。 \n", "\n", - "## `__init__.py` 包文件 \n", + "## 1.2 `__init__.py` 包文件 \n", "包导入语句的路径中的每个目录内都必须有 `__init__.py` 这个文件,否则导入包会失败。 \n", "\n", "对于如下目录结构:\n", @@ -142,7 +142,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 从包中使用 * 导入 \n", + "# 2. 从包中使用 * 导入 \n", "当一个包中有多个文件时,当使用 `from import *` 时,不会导入任何模块。Python 遵循这样的约定:如果 `__init__.py` 文件在包目录中包含一个名为 `__all__` 的列表,则它被认为是当遇到 `from import *` 的语句时应该导入的模块列表。" ] }, @@ -178,8 +178,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 包相对导入 \n", - "## 相对导入基础知识 \n", + "# 3. 包相对导入 \n", + "## 3.1 相对导入基础知识 \n", "from 语句可以使用前面的点号来指定,它们需要位于同一包中的模块(相对导入),而不是位于模块导入搜索路径上某处的模块(绝对导入):\n", "- **使用点号导入。**这样的导入将只在包的内部搜索,并不会搜索位于搜索路径上某处的同名模块。直接效果是包模块覆盖了外部的模块。\n", "- **不使用点号导入。**在一个包中导入默认是绝对路径的,导入忽略了包含包自身并在 sys.path 路径上的某处查找。 \n", @@ -207,11 +207,11 @@ "from ..E import X # 导入 A.E.X(..代表 A)\n", "```\n", "\n", - "## 相对导入的作用域 \n", + "## 3.2 相对导入的作用域 \n", "- **相对导入适用于只在包内导入。**\n", "- **相对导入只适用于 from 语句。** \n", "\n", - "## 模块查找规则总结 \n", + "## 3.3 模块查找规则总结 \n", "- 简单模块名(例如,A)通过搜索 sys.path 路径列表上的每个目录来查找,从左到右进行。这个列表由系统默认设置和用户配置设置组成。\n", "- 包是带有一个特殊的 `__init__py.` 文件的 Python 模块的直接目录,这使得一个导入中可以使用 A.B.C 目录路径语法。在 A.B.C 的一条导入中,名为 A 的目录位于相对于 sys.path 的常规模块导入搜索,B 是 A 中的另一个包子目录,C 是一个模块或 B 中的其他可导入项。\n", "- 在一个包文件中,常规的 import 和 from 语句使用和其他地方的导入一样的 sys.path 搜索规则。包中的导入使用 from 语句以及前面的点号,然而,它是相对于包的;也就是说,只检查包目录,并且不使用常规的 sys.path 查找。" @@ -221,14 +221,14 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Python 3.3 的命名空间包 \n", + "# 4. Python 3.3 的命名空间包 \n", "Python 3.3 之后有四种导入模型:\n", "- **基本模块导入:**import mod, from mod import attr\n", "- **包导入:**import dir1.dir2.mod, from dir1.mod import attr\n", "- **包相对导入:**from . import mod(相对), import mod(绝对)\n", "- **命名空间包:**import splitdir.mod,允许包扩展多个目录,不需要初始化文件。\n", "\n", - "## 命名空间包语义 \n", + "## 4.1 命名空间包语义 \n", "**import 算法** \n", "1. 如果找到 `directory\\spam\\__init__.py` 文件,常规包被导入和返回。\n", "2. 如果找到 `directory\\spam.{py, pyc, 或其他模块扩展}`,一个简单模块被导入和返回。\n", @@ -237,7 +237,7 @@ "\n", "如果搜索路径扫描完成,没有在步骤1或步骤2中返回模块或包,在步骤3中记录到至少一个目录,则命名空间包被创建。新的命名空间包有一个 `__path__` 属性,包含找到的目录路径字符串,在步骤3的扫描中记录。一旦命名空间包被创建,和传统包就没有功能上的不同。 \n", "\n", - "## 对传统包的影响:可选的 `__init__.py` 文件 \n", + "## 4.2 对传统包的影响:可选的 `__init__.py` 文件 \n", "Python 3.3 的包不再需要 `__init__.py` 文件——当单个目录包没有这个文件,则会被当做一个单目录命名空间包。许多包不需要初始化代码。传统包模型依旧完全支持,自动运行 `__init__.py` 文件中的代码。 " ] }, @@ -265,7 +265,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.6" + "version": "3.6.8" } }, "nbformat": 4, From 10b9e7ac7b82fd43062bdbeb01309ab947caece4 Mon Sep 17 00:00:00 2001 From: Lanxin <675579465@qq.com> Date: 2019年9月27日 13:51:39 +0800 Subject: [PATCH 3/7] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E9=AB=98=E7=BA=A7?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=E8=AF=9D=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...345235円227円350円257円235円351円242円230円.ipynb" | 33 +++++++++++-------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git "a/Learning Python/5343円200円201円346円250円241円345円235円227円345円222円214円345円214円205円/4. 351円253円230円347円272円247円346円250円241円345円235円227円350円257円235円351円242円230円.ipynb" "b/Learning Python/5343円200円201円346円250円241円345円235円227円345円222円214円345円214円205円/4. 351円253円230円347円272円247円346円250円241円345円235円227円350円257円235円351円242円230円.ipynb" index b3da92b..edb7baa 100644 --- "a/Learning Python/5343円200円201円346円250円241円345円235円227円345円222円214円345円214円205円/4. 351円253円230円347円272円247円346円250円241円345円235円227円350円257円235円351円242円230円.ipynb" +++ "b/Learning Python/5343円200円201円346円250円241円345円235円227円345円222円214円345円214円205円/4. 351円253円230円347円272円247円346円250円241円345円235円227円350円257円235円351円242円230円.ipynb" @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 模块设计理念 \n", + "# 1. 模块设计理念 \n", "- **总是在 Python 的模块内编写代码。** \n", "- **最小化模块耦合性:全局变量。**\n", "- **最大化模块粘合性:统一目标。** \n", @@ -15,10 +15,10 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 在模块中隐藏数据 \n", + "# 2. 在模块中隐藏数据 \n", "Python 模块会导出其文件顶层所赋值的所有变量名,没有对某一个变量名进行声明,使其在模块内可见或不可见这种概念。 \n", "\n", - "## 最小化 from * 的破坏:`_X` 和 `__all__` \n", + "## 2.1 最小化 from * 的破坏:`_X` 和 `__all__` \n", "把下划线放在变量名前面(例如,_X),可以防止客户端使用 from * 语句导入模块名时,把其中的那些变量名复制出去。但还是可以使用其他导入形式看见并修改这些变量名,例如 import 语句。" ] }, @@ -201,7 +201,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 启用未来的语言特性:__future__ \n", + "# 3. 启用未来的语言特性:__future__ \n", "代码语言方面的变动可能破坏现有代码,使用以下形式的特定的 import 语句开启扩展功能:\n", "```\n", "from __future__ import featurename\n", @@ -213,7 +213,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 混合用法模式:__name__ 和 __main__ \n", + "# 4. 混合用法模式:`__name__` 和 `__main__` \n", "这个技巧可以把文件作为模块导入,并以独立式程序的形式运行。每个模块都有个名为 `__name__` 的内置属性,Python 会自动设置该属性:\n", "- 如果文件是以顶层程序文件执行,在启动时,`__name__` 就会设置为字符串 `\"__main__\"`。\n", "- 如果文件被导入,`__name__` 就会改设成客户端所了解的模块名。\n", @@ -298,7 +298,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 示例:双模代码 \n", + "# 5. 示例:双模代码 \n", "如下的模块 formats.py,为导入者定了字符串格式化工具,还检查其名称看它是否作为一个顶层脚本在运行;如果是这样的话,它测试并使用系统命令行上列出的参数来运行一个定制的或传入的测试。在 Python 中,sys.argv 列表包含了命令行参数,它是反映在命令行上录入的单词的一个字符串列表,其中,第一项总是将要运行的脚本的名称: " ] }, @@ -482,7 +482,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 修改模块搜索路径 \n", + "# 6. 修改模块搜索路径 \n", "模块搜索路径是一个目录列表,可以通过环境变量 PYTHONPATH 以及可能的 .pth 路径文件进行定制。Python 程序本身通过修改名为 sys.path 的内置列表来修改搜索路径。sys.path 在程序启动时就会进行初始化,在那之后,可以随意对其元素进行删除、附加和重设:" ] }, @@ -583,7 +583,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Import 语句和 from 语句的 as 扩展 \n", + "# 7. Import 语句和 from 语句的 as 扩展 \n", "import 和 from 语句都可以扩展,让模块可以在脚本中给予不同的变量名:\n", "```\n", "import modulename as name\n", @@ -608,7 +608,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 用名称字符串导入模块 \n", + "# 8. 用名称字符串导入模块 \n", "有时候,我们的程序可以在运行时以一个字符串的形式获取要导入的模块的名称。使用特殊的工具,从运行时生成的一个字符串来动态地载入一个模块。最通用的方法是,把一条导入语句构建为 Python 代码的一个字符串,并且将其传递给 exec 内置函数以运行:" ] }, @@ -694,12 +694,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 示例:过渡性模块重载 \n", + "# 9. 示例:过渡性模块重载 \n", "当重载一个模块时,Python 只重载特定的模块文件,它不会自动重载那些导入的模块。 \n", "\n", "例如,要重载某个模块 A,并且 A 导入模块 B 和 C,重载只适用于 A,而不适用于 B 和 C。 \n", "\n", - "## 递归重载 \n", + "## 9.1 递归重载 \n", "通过扫描模块的 `__dict__` 属性并检查每一项的 type 以找到要重新载入的嵌套模块:" ] }, @@ -802,7 +802,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 模块陷阱 \n", + "# 10. 模块陷阱 \n", "- **顶层代码的语句次序的重要性。**\n", "- **from 复制变量名,而不是连接。**\n", "- **from * 会让变量语义模糊。**\n", @@ -810,6 +810,13 @@ "- **reload、from 以及交互式模式测试。**\n", "- **递归形式的 from 导入无法工作。**" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { @@ -828,7 +835,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.6" + "version": "3.6.8" } }, "nbformat": 4, From c4e266af08365976bb2415ff1415c6d82e25f837 Mon Sep 17 00:00:00 2001 From: Lanxin <675579465@qq.com> Date: 2019年9月29日 16:23:47 +0800 Subject: [PATCH 4/7] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=B1=BB=E5=92=8COOP?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...344274円237円350円223円235円345円233円276円.ipynb" | 19 ++++-- ...345206円231円345円237円272円347円241円200円.ipynb" | 24 ++++---- ...347232円204円344円276円213円345円255円220円.ipynb" | 44 ++++++------- ...345206円231円347円273円206円350円212円202円.ipynb" | 43 +++++++------ ...347254円246円351円207円215円350円275円275円.ipynb" | 46 +++++++------- ...347232円204円350円256円276円350円256円241円.ipynb" | 30 ++++----- ...347272円247円344円270円273円351円242円230円.ipynb" | 61 +++++++++++-------- ...346226円260円347円211円271円346円200円247円.ipynb" | 4 +- 8 files changed, 146 insertions(+), 125 deletions(-) diff --git "a/Learning Python/6343円200円201円347円261円273円345円222円214円 OOP/1. OOP357円274円232円345円256円217円344円274円237円350円223円235円345円233円276円.ipynb" "b/Learning Python/6343円200円201円347円261円273円345円222円214円 OOP/1. OOP357円274円232円345円256円217円344円274円237円350円223円235円345円233円276円.ipynb" index 65eb5d9..0a89f48 100644 --- "a/Learning Python/6343円200円201円347円261円273円345円222円214円 OOP/1. OOP357円274円232円345円256円217円344円274円237円350円223円235円345円233円276円.ipynb" +++ "b/Learning Python/6343円200円201円347円261円273円345円222円214円 OOP/1. OOP357円274円232円345円256円217円344円274円237円350円223円235円345円233円276円.ipynb" @@ -9,8 +9,8 @@ "- **通过继承进行定制。**\n", "- **运算符重载。**\n", "\n", - "# 概览 OOP \n", - "## 属性继承搜索 \n", + "# 1. 概览 OOP \n", + "## 1.1 属性继承搜索 \n", "Python 中大多数 OOP 的故事,都可简化成以下表达式:\n", "```\n", "object.attribute\n", @@ -20,13 +20,13 @@ "\n", "我们称这种搜索程序为继承,树中位置较低的对象继承了树中位置较高的对象拥有的属性。当从下至上进行搜索时,连接至树中的对象就是树中所有上层对象所定义的所有属性的集合体,直到树的最顶端。 \n", "\n", - "## 类和实例 \n", + "## 1.2 类和实例 \n", "类和实例是两种不同的对象类型,主要差异在于,类是一种产生实例的工厂,内存中特定模块只有一个实例,对类而言,只要有需要,制作多少实例都可以。 \n", "\n", - "## 类方法调用 \n", + "## 1.3 类方法调用 \n", "如果 I2.w 引用是一个函数调用,其实际的含义是"调用 C3.w 函数以处理 I2"。Python 会自动将 I2.w() 调用映射为 C3.w(I2) 调用,传入该实例作为继承的函数的第一个参数。 \n", "\n", - "## 编写类树 \n", + "## 1.4 编写类树 \n", "- 每个 class 语句会生成一个新的类对象。\n", "- 每次类调用时,就会生成一个新的实例对象。\n", "- 实例自动连接至创建了这些实例的类。\n", @@ -34,6 +34,13 @@ "\n", "属性通常是在 class 语句中通过赋值语句添加在类中,而不是嵌入在函数的 def 语句内;属性通常是在类内,对传给函数的特殊参数(也就是 self),做赋值运算而添加在实例中的。 " ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { @@ -52,7 +59,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.5" + "version": "3.6.8" } }, "nbformat": 4, diff --git "a/Learning Python/6343円200円201円347円261円273円345円222円214円 OOP/2. 347円261円273円344円273円243円347円240円201円347円274円226円345円206円231円345円237円272円347円241円200円.ipynb" "b/Learning Python/6343円200円201円347円261円273円345円222円214円 OOP/2. 347円261円273円344円273円243円347円240円201円347円274円226円345円206円231円345円237円272円347円241円200円.ipynb" index 9bffdcb..849064d 100644 --- "a/Learning Python/6343円200円201円347円261円273円345円222円214円 OOP/2. 347円261円273円344円273円243円347円240円201円347円274円226円345円206円231円345円237円272円347円241円200円.ipynb" +++ "b/Learning Python/6343円200円201円347円261円273円345円222円214円 OOP/2. 347円261円273円344円273円243円347円240円201円347円274円226円345円206円231円345円237円272円347円241円200円.ipynb" @@ -4,20 +4,20 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 类产生多个实例对象 \n", - "## 类对象提供默认行为 \n", + "# 1. 类产生多个实例对象 \n", + "## 1.1 类对象提供默认行为 \n", "Python 类主要特性的要点:\n", "- **class 语句创建类对象并将其赋值给变量名。**\n", "- **class 语句内的赋值语句会创建类的属性。**\n", "- **类属性提供对象的状态和行为。**\n", "\n", - "## 实例对象是具体的元素 \n", + "## 1.2 实例对象是具体的元素 \n", "类的实例内含的重点概要:\n", "- **像函数那样调用类对象会创建新的实例对象。**\n", "- **每个实例对象继承类的属性并获得了自己的命名空间。**\n", "- **在方法内对 self 属性做赋值运算会产生每个实例自己的属性。**在类方法函数内,第一个参数(self)会引用正处理的实例对象。\n", "\n", - "## 第一个例子 " + "## 1.3 第一个例子 " ] }, { @@ -138,7 +138,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 类通过继承进行定制 \n", + "# 2. 类通过继承进行定制 \n", "类可以引入新组件(子类)来进行修改,而不对现有组件进行原地的修改。由类产生的实例对象会继承该类的属性。 \n", "\n", "属性继承机制的核心观点:\n", @@ -148,7 +148,7 @@ "- **每个 object.attribute 都会开启新的独立搜索。**\n", "- **逻辑的修改是通过创建子类,而不是修改超类。**在树中层次较低的子类中重新定义超类的变量名,子类就可取代并制定所继承的行为。\n", "\n", - "## 第二个例子 \n", + "## 2.1 第二个例子 \n", "定义一个新的类 SecondClass,继承 FirstClass 所有变量名,并提供其自己的一个变量名:" ] }, @@ -210,7 +210,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 类是模块内的属性 \n", + "## 2.2 类是模块内的属性 \n", "类名称总是存在于模块中,class 语句会在导入时执行已定义的变量名,而这些变量名会变成独立的模块属性。" ] }, @@ -218,7 +218,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 类可以截获 Python 运算符 \n", + "# 3. 类可以截获 Python 运算符 \n", "运算符重载就是让用类写成的对象,可截获并响应用在内置类型上的运算:加法、切片、打印和点号运算等。 \n", "\n", "重载运算符主要概念的概要:\n", @@ -230,7 +230,7 @@ "\n", "运算符重载是可选的功能,除非类需要模仿内置类型接口,不然应该使用更简单的命名方法。 \n", "\n", - "## 第三个例子 \n", + "## 3.1 第三个例子 \n", "定义 SecondClass 的子类,实现三个特殊名称的属性,让 Python 自动进行调用:\n", "- 当新的实例构造时,会调用 `__init__`(self 是新的 ThirdClass 对象)。\n", "- 当 ThirdClass 实例出现在 + 表达式中时,则会调用 `__add__`。\n", @@ -346,7 +346,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 世界上最简单的 Python 类 " + "# 4. 世界上最简单的 Python 类 " ] }, { @@ -572,7 +572,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 类与字典的关系 \n", + "## 4.1 类与字典的关系 \n", "利用类来记录属性,可以用不同的实例记录不同的数据,模拟字典的方法:" ] }, @@ -605,7 +605,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.5" + "version": "3.6.8" } }, "nbformat": 4, diff --git "a/Learning Python/6343円200円201円347円261円273円345円222円214円 OOP/3. 344円270円200円344円270円252円346円233円264円345円256円236円351円231円205円347円232円204円344円276円213円345円255円220円.ipynb" "b/Learning Python/6343円200円201円347円261円273円345円222円214円 OOP/3. 344円270円200円344円270円252円346円233円264円345円256円236円351円231円205円347円232円204円344円276円213円345円255円220円.ipynb" index f620ef3..0506648 100644 --- "a/Learning Python/6343円200円201円347円261円273円345円222円214円 OOP/3. 344円270円200円344円270円252円346円233円264円345円256円236円351円231円205円347円232円204円344円276円213円345円255円220円.ipynb" +++ "b/Learning Python/6343円200円201円347円261円273円345円222円214円 OOP/3. 344円270円200円344円270円252円346円233円264円345円256円236円351円231円205円347円232円204円344円276円213円345円255円220円.ipynb" @@ -8,7 +8,7 @@ "- Person——创建并处理关于人员的信息的一个类\n", "- Manager——一个定制的 Person,修改了继承的行为。\n", "\n", - "# 步骤1:创建实例 \n", + "# 1. 步骤1:创建实例 \n", "在 Python 中,模块名使用小写字母开头,类名使用一个大写字母开头:" ] }, @@ -26,7 +26,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 编写构造函数 \n", + "## 1.1 编写构造函数 \n", "赋给实例属性第一个值的通常方法是,在 `__init__` 构造函数方法中将它们赋给 self,构造函数方法包含了每次创建一个实例的时候 Python 会自动运行的代码:" ] }, @@ -50,7 +50,7 @@ "source": [ "job 参数在 `__init__` 函数的作用域里是一个本地变量,但是 self.job 是实例的一个属性,它暗示了方法调用的内容。 \n", "\n", - "## 在进行中测试 \n", + "## 1.2 在进行中测试 \n", "常见的做法是,Python 程序员使用交互式提示来进行简单的一次性测试,但是通过在包含测试对象的文件的底部编写代码来进行更多的大量测试:" ] }, @@ -86,7 +86,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 以两种方式使用代码 \n", + "## 1.3 以两种方式使用代码 \n", "文件底部的测试代码是有用的,但是当文件作为脚本运行的时候,或者当它作为一个模块导入的时候,顶层的 print 都会运行,这不是一种很好的软件关系。" ] }, @@ -131,7 +131,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 步骤2:添加行为方法 \n", + "# 2. 步骤2:添加行为方法 \n", "尽管类添加了结构的一个额外的层级,它们最终还是通过嵌入和处理列表及字符串这样的基本核心数据类型来完成其大部分工作。" ] }, @@ -181,7 +181,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 编写方法 \n", + "## 2.1 编写方法 \n", "这里借用一种叫做**封装**的软件设计概念,封装的思想就是把操作逻辑包装到界面之后,这样,每种操作在我们程序里只编码一次。通过这种方式,如果将来需要修改,只需要修改一个版本。 \n", "\n", "把操作放入方法中,使得这些操作可以应用于类的任何实例,而不是仅能用于把它们硬编码来处理的那些对象。" @@ -236,10 +236,10 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 步骤3:运算符重载 \n", + "# 3. 步骤3:运算符重载 \n", "当前,测试还是不能像所需要的那样方便——要跟踪对象,必须手动地接受和打印单个的属性。如果一次显示一个实例真的能给我们一些有用的信息,那还是不错的。但是,实例对象的默认显示格式并不是很好,它显示对象的类名及其在内存中的地址。 \n", "\n", - "## 提供打印显示 \n", + "## 3.1 提供打印显示 \n", "通过**运算符重载**可以很容易做得更好,使用 `__repr__` 方法,`__str__` 的双胞胎方法。 \n", "\n", "从技术上讲,`__str__` 是 print 和 str 的首选,`__repr__` 被用作这些角色和所有其他上下文中的后备。虽然这两种方法可以用于在不同的上下文中实现不同的显示,但是仅通过编写 `__repr__` 就足以在所有情况下——打印、嵌套显示和交互回显中提供显示。这仍然允许客户端提供 `__str__` 的替代显示,但仅限于有限的上下文。" @@ -296,8 +296,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 步骤4:通过子类定制行为 \n", - "## 扩展方法:不好的方式 \n", + "# 4. 步骤4:通过子类定制行为 \n", + "## 4.1 扩展方法:不好的方式 \n", "复制和粘贴 Person 中的 giveRaise 代码。" ] }, @@ -316,7 +316,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 扩展方法:好的方式 \n", + "## 4.2 扩展方法:好的方式 \n", "使用扩展的参数来直接调用其最初的版本:" ] }, @@ -392,7 +392,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 步骤5:定制构造函数 \n", + "# 5. 步骤5:定制构造函数 \n", "重新定义 Manager 中的 `__init__` 方法,从而提供 mgr 字符串,通过类名的调用来运行 Person 中最初的 `__init__`,以便它仍然会初始化对象的状态信息属性。" ] }, @@ -452,12 +452,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 步骤6:使用内省工具 \n", + "# 6. 步骤6:使用内省工具 \n", "现在仍有两个问题:\n", "- 当打印 tom 时,Manager 会把它标记为 Person。\n", "- 当前的显式格式只是显式了包含在 `__repr__` 中的属性,而没有考虑未来的目标。如果更改了在 `__init__` 中分配给对象的属性集合,那么还必须也要更新 `__repr__` 以显示新的名字。\n", "\n", - "## 特殊类属性 \n", + "## 6.1 特殊类属性 \n", "可以使用 Python 的**内省工具**来解决这两个问题,它们是特殊的属性和函数,允许我们访问对象实现的一些内部机制。有两个 hook 可以帮助解决问题:\n", "- 内置的 `instance.__class__` 属性提供了一个从实例到创建它的类的链接。类反过来有一个 `__name__`,还有一个 `__bases__` 序列,提供了超类的访问。\n", "- 内置的 `object.__dict__` 属性提供了一个字典,以便每个属性都附加到一个命名控件对象。" @@ -546,7 +546,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 一种通用显示工具 " + "## 6.2 一种通用显示工具 " ] }, { @@ -609,7 +609,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 类的最终形式 " + "## 6.3 类的最终形式 " ] }, { @@ -673,10 +673,10 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 步骤7:把对象存储到数据库中 \n", + "# 7. 步骤7:把对象存储到数据库中 \n", "尽管类按照计划工作,但它们创建的对象还不是真正的数据库记录,如果关闭 Python,实例也将消失。Python 的一项**对象持久化**功能能让对象在创建它们的程序退出之后依然存在。 \n", "\n", - "## Pickle 和 Shelve \n", + "## 7.1 Pickle 和 Shelve \n", "对象持久化通过三个标准的库模块来实现:\n", "- **pickle。**任意 Python 对象和字节字符串之间的序列化\n", "- **dbm。**实现一个可通过键访问的文件系统,以存储字符串\n", @@ -684,7 +684,7 @@ "\n", "shelve 使用 pickle 把一个对象转换为其 pickle 化的字符串,并将其存储在一个 dbm 文件中的键之下;随后载入的时候,shelve 通过键获取 pickle 化的字符串,并用 pickle 在内存中重新创建最初的对象。 \n", "\n", - "## 在 shelve 数据库中存储对象 \n", + "## 7.2 在 shelve 数据库中存储对象 \n", "编写 makedb.py 文件:" ] }, @@ -712,7 +712,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 交互地探索 shelve \n", + "## 7.3 交互地探索 shelve \n", "此时,当前目录下会有多个文件,名字都以"persondb"开头。" ] }, @@ -886,7 +886,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 更新 shelve 中的对象 \n", + "## 7.4 更新 shelve 中的对象 \n", "在每次运行的时候更新一个实例。" ] }, @@ -1010,7 +1010,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.5" + "version": "3.6.8" } }, "nbformat": 4, diff --git "a/Learning Python/6343円200円201円347円261円273円345円222円214円 OOP/4. 347円261円273円344円273円243円347円240円201円347円274円226円345円206円231円347円273円206円350円212円202円.ipynb" "b/Learning Python/6343円200円201円347円261円273円345円222円214円 OOP/4. 347円261円273円344円273円243円347円240円201円347円274円226円345円206円231円347円273円206円350円212円202円.ipynb" index 1100c50..4dcdb81 100644 --- "a/Learning Python/6343円200円201円347円261円273円345円222円214円 OOP/4. 347円261円273円344円273円243円347円240円201円347円274円226円345円206円231円347円273円206円350円212円202円.ipynb" +++ "b/Learning Python/6343円200円201円347円261円273円345円222円214円 OOP/4. 347円261円273円344円273円243円347円240円201円347円274円226円345円206円231円347円273円206円350円212円202円.ipynb" @@ -4,10 +4,10 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# class 语句 \n", + "# 1. class 语句 \n", "Python 的 class 并不是声明式的,class 语句是对象的创建者并且是一个隐含的赋值运算。 \n", "\n", - "## 一般形式 \n", + "## 1.1 一般形式 \n", "class 是复合语句。在头一行中,超类列在类名称之后的括号内,由逗号相隔。列出一个以上的超类会引起多重继承: \n", "```\n", "class name(superclass, ...): # 赋值给变量名\n", @@ -15,7 +15,7 @@ " def method(self, ...):\n", " self.member = value\n", "```\n", - "## 例子 \n", + "## 1.2 例子 \n", "当 Python 执行 class 语句时(不是调用类),会从头至尾执行其主体内的所有语句。在这个过程中,进行的赋值运算会在这个类作用域中创建变量名,从而成为对应的类对象内的属性。类就像模块和函数:\n", "- 就像函数一样,class 语句是本地作用域,由内嵌的赋值语句建立的变量名,就存在于这个本地作用域内。\n", "- 就像模块内的变量名,在 class 语句内赋值的变量名会变成类对象中的属性。\n", @@ -130,12 +130,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 方法 \n", + "# 2. 方法 \n", "方法位于 class 语句的主体内,是由 def 语句建立的函数对象。方法的第一个参数总是接收方法调用的隐形主体,也就是实例对象。 \n", "\n", "在类方法中,按惯例第一个参数通常都称为 self。这个参数给方法提供了一个 hook,从而返回调用的主体,也就是实例对象。 \n", "\n", - "## 例子 " + "## 2.1 例子 " ] }, { @@ -183,7 +183,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 调用超类构造函数 \n", + "## 2.2 调用超类构造函数 \n", "在构造时,Python 会找出并且只调用一个 `__init__`。如果要保证子类的构造函数也会执行超类构造时的逻辑,一般都必须通过类明确地调用超类的 `__init__` 方法:" ] }, @@ -209,15 +209,15 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 继承 \n", + "# 3. 继承 \n", "当对对象进行点号运算时,就会发生继承,而且涉及了搜索属性定义树(一个或多个命名空间)。 \n", "\n", - "## 属性树的构造 \n", + "## 3.1 属性树的构造 \n", "- 实例属性是由对方法内 self 属性进行赋值运算而生成的。\n", "- 类属性是通过 class 语句内的语句(赋值语句)而生成的。\n", "- 超类的连接是通过 class 语句首行的括号内列出类而生成的。\n", "\n", - "## 继承方法的专有化 \n", + "## 3.2 继承方法的专有化 \n", "继承会现在子类寻找变量名,然后才查找超类,子类就可以对超类的属性重新定义来取代默认的行为。" ] }, @@ -273,7 +273,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 抽象超类 \n", + "## 3.3 抽象超类 \n", "类的部分行为默认是由其子类所提供的。如果预期的方法没有在子类中定义,当继承搜索失败时,Python 会引发未定义变量名的异常。 " ] }, @@ -281,21 +281,21 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 命名空间:完整的内容 \n", + "# 4. 命名空间:完整的内容 \n", "- 无点号运算的变量名与作用域相对应。\n", "- 点号的属性名使用的是对象的命名空间。\n", "- 有些作用域会对对象的命名空间进行初始化(模块和类)。\n", "\n", - "## 简单变量名:如果赋值就不是全局变量 \n", + "## 4.1 简单变量名:如果赋值就不是全局变量 \n", "无点号的简单变量名遵循 LEGB 作用域法则:\n", "- **赋值语句(X = value)。**使变量名成为本地变量:在当前作用域内,创建或改变变量名 X,除非声明它是全局变量。\n", "- **引用(X)。**在当前作用域内搜索变量名 X,之后是在任何以及所有的嵌套的函数中,然后是在当前的全局作用域中搜索,最后在内置作用域中搜索。\n", "\n", - "## 属性名称:对象命名空间 \n", + "## 4.2 属性名称:对象命名空间 \n", "- **赋值语句(object.X = value)。**在进行点号运算的对象的命名空间内创建或修改属性名 X。继承树的搜索只发生在属性引用时,而不是属性的赋值运算时。\n", "- **引用(object.X)。**就基于类的对象而言,会在对象内搜索属性名 X,然后是其上所有可读取的类。对于不是基于类的对象而言,则是从对象中直接读取 X。\n", "\n", - "## 嵌套类 \n", + "## 4.3 嵌套类 \n", "类有时在函数中进行嵌套,并生成,这是闭包的一种变体。" ] }, @@ -428,7 +428,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 命名空间字典 \n", + "## 4.4 命名空间字典 \n", "属性点号运算其实内部就是字典的索引运算,而属性继承其实就是搜索链接的字典。" ] }, @@ -691,7 +691,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 命名空间链接:树爬升 \n", + "## 4.5 命名空间链接:树爬升 \n", "可以用实例和类的特殊属性 `__class__` 和 `__bases__` 来显示类树:" ] }, @@ -755,7 +755,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 类与模块的关系 \n", + "# 5. 类与模块的关系 \n", "- **模块**\n", " - 是数据/逻辑包。\n", " - 通过编写 Python 文件或 C 扩展来创建。\n", @@ -766,6 +766,13 @@ " - 通过调用来使用。\n", " - 总是位于一个模块中。" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { @@ -784,7 +791,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.5" + "version": "3.6.8" } }, "nbformat": 4, diff --git "a/Learning Python/6343円200円201円347円261円273円345円222円214円 OOP/5. 350円277円220円347円256円227円347円254円246円351円207円215円350円275円275円.ipynb" "b/Learning Python/6343円200円201円347円261円273円345円222円214円 OOP/5. 350円277円220円347円256円227円347円254円246円351円207円215円350円275円275円.ipynb" index 8810d2e..463ae67 100644 --- "a/Learning Python/6343円200円201円347円261円273円345円222円214円 OOP/5. 350円277円220円347円256円227円347円254円246円351円207円215円350円275円275円.ipynb" +++ "b/Learning Python/6343円200円201円347円261円273円345円222円214円 OOP/5. 350円277円220円347円256円227円347円254円246円351円207円215円350円275円275円.ipynb" @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 基础知识 \n", + "# 1. 基础知识 \n", "运算符重载意味着在类方法中拦截内置的操作——当类的实例出现在内置操作中,Python 会自动调用你的方法,并且你的方法的返回值变成了相应操作的结果:\n", "- 运算符重载让类拦截常规的 Python 运算。\n", "- 类可重载所有 Python 表达式运算符。\n", @@ -12,7 +12,7 @@ "- 重载使类实例的行为像内置类型。\n", "- 重载是通过提供特殊名称的类方法来实现的。\n", "\n", - "## 构造函数和表达式:`___init___` 和 `___sub___` " + "## 1.1 构造函数和表达式:`___init___` 和 `___sub___` " ] }, { @@ -54,7 +54,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 常见的运算符重载方法 \n", + "## 1.2 常见的运算符重载方法 \n", "\n", "方法|重载|调用\n", "---|---|---\n", @@ -91,7 +91,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 索引和分片:`__getitem__` 和 `__setitem__` \n", + "# 2. 索引和分片:`__getitem__` 和 `__setitem__` \n", "如果在类中定义了(或继承了)的话,则对于实例的索引运算,会自动调用 `__getitem__`。" ] }, @@ -142,7 +142,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 拦截分片 \n", + "## 2.1 拦截分片 \n", "对于**分片表达式**也调用 `__getitem__`。" ] }, @@ -245,7 +245,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 索引迭代:`__getitem__` \n", + "# 3. 索引迭代:`__getitem__` \n", "`__getitem__` 可以使 Python 中一种重载迭代的方式。如果定义了这个方法,for 循环每次循环时都会调用类的 `__getitem__`,并持续搭配有更高的偏移值。" ] }, @@ -337,10 +337,10 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 迭代器对象:`__iter__` 和 `__next__` \n", + "# 4. 迭代器对象:`__iter__` 和 `__next__` \n", "Python 中所有的迭代环境都会先尝试 `__iter__` 方法,再尝试 `__getitem__`。只有在对象不支持迭代协议的时候,才会尝试索引运算。 \n", "\n", - "## 用户定义的迭代器 " + "## 4.1 用户定义的迭代器 " ] }, { @@ -425,7 +425,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 有多个迭代器的对象 \n", + "## 4.2 有多个迭代器的对象 \n", "要达到多个迭代器的效果,`__iter__` 只需替迭代器定义新的状态对象,而不是返回 self。 \n", "\n", "在某些应用中,还可以将 `__iter__` 方法和 yield 生成器函数表达式结合在一起。因为生成器函数自动保存本地变量状态并且创建需要的迭代器方法。调用生成器函数时,自动创建 `__iter__` 方法,简单地返回自身。" @@ -533,7 +533,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 成员关系:`__contains__`、`__iter__` 和 `__getitem__` \n", + "## 4.3 成员关系:`__contains__`、`__iter__` 和 `__getitem__` \n", "运算符重载往往是**多个层级的**:类可以提供特定的方法,或者用作退而求其次选项的更通用的替代方案。 \n", "\n", "在迭代领域,类通常把 in 成员关系运算符实现为一个迭代,使用 `__iter__` 方法或 `__getitem__` 方法。要支持更加特定的成员关系,类可能编写一个 `__contains__` 方法——该方法优先于 `__iter__` 方法,`__iter__` 方法优先于 `__getitem__` 方法。`__contains__` 方法应该把成员关系定义为对一个**映射**应用键,以及用于**序列**的搜索。" @@ -727,8 +727,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 属性访问:`__getattr__` 和 `__setattr__` \n", - "## 属性引用 \n", + "# 5. 属性访问:`__getattr__` 和 `__setattr__` \n", + "## 5.1 属性引用 \n", "`__getattr__` 方法是拦截属性点号运算。当通过对**未定义**属性名称和实例进行点号运算时,就会用属性名称作为字符串调用这个方法。如果 Python 可通过其继承树搜索流程找到这个属性,该方法就不会被调用。`__getattr__` 可以作为 hook 来通过通用的方式响应属性请求:" ] }, @@ -793,7 +793,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 属性赋值和删除 \n", + "## 5.2 属性赋值和删除 \n", "`__setattr__` 会拦截所有属性的赋值语句。如果定义或继承了这个方法,`self.attr = value` 会变成 `self.__setattr__('attr', value)`。 \n", "\n", "在 `__setattr__` 中对任何 self 属性做赋值,都会再调用 `__setattr__`,导致了无穷递归循环。如果想使用这个方法,要确定是通过对属性字典做索引运算来赋值任何实例属性。也就是说,使用 `self.__dict__['name'] = x`,而不是 `self.name = x`:" @@ -861,7 +861,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 模拟实例属性的私有化:第一部分 \n", + "# 6. 模拟实例属性的私有化:第一部分 \n", "每个子类都有自己的私有变量名列表,这些变量名无法通过其实例进行赋值:" ] }, @@ -1000,7 +1000,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 字符串表示:`__repr__` 和 `__str__` \n", + "# 7. 字符串表示:`__repr__` 和 `__str__` \n", "当定义时,类的实例打印或转换成字符串时 `__repr__` 或 `__str__` 就会自动调用。这些方法可替对象定义更好的显式格式。" ] }, @@ -1277,8 +1277,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 右侧加法和原处加法:`__radd__` 和 `__iadd__` \n", - "## 右侧加法 \n", + "# 8. 右侧加法和原处加法:`__radd__` 和 `__iadd__` \n", + "## 8.1 右侧加法 \n", "`__add__` 方法并不支持 + 运算符右侧使用实例对象:" ] }, @@ -1442,7 +1442,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 原处加法 " + "## 8.2 原处加法 " ] }, { @@ -1479,7 +1479,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Call 表达式:`__call__` \n", + "# 9. Call 表达式:`__call__` \n", "当调用实例时,使用 `__call__` 方法:" ] }, @@ -1582,7 +1582,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 比较:`__lt__`、`__gt__` 和其他方法 \n", + "# 10. 比较:`__lt__`、`__gt__` 和其他方法 \n", "- 与`__add__`/`__radd__` 对不同,比较方法没有右端形式。\n", "- 比较运算符没有隐式关系。例如,== 并不意味着 != 是假的。" ] @@ -1618,7 +1618,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 布尔测试:`__bool__` 和 `__len__` \n", + "# 11. 布尔测试:`__bool__` 和 `__len__` \n", "在布尔环境中,Python 首先尝试 `__bool__` 来获取一个直接的布尔值,如果没有该方法,就尝试 `__len__` 类根据对象的长度确定一个真值。通常,首先使用对象状态或其他信息来生成一个布尔结果:" ] }, @@ -1731,7 +1731,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 对象析构函数:`__del__` \n", + "# 12. 对象析构函数:`__del__` \n", "每当实例产生时,就会调用 `__init__` 构造函数。每当实例空间被收回时,就会自动执行 `__del__` 析构函数:" ] }, @@ -1826,7 +1826,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.5" + "version": "3.6.8" } }, "nbformat": 4, diff --git "a/Learning Python/6343円200円201円347円261円273円345円222円214円 OOP/6. 347円261円273円347円232円204円350円256円276円350円256円241円.ipynb" "b/Learning Python/6343円200円201円347円261円273円345円222円214円 OOP/6. 347円261円273円347円232円204円350円256円276円350円256円241円.ipynb" index 750f748..982222f 100644 --- "a/Learning Python/6343円200円201円347円261円273円345円222円214円 OOP/6. 347円261円273円347円232円204円350円256円276円350円256円241円.ipynb" +++ "b/Learning Python/6343円200円201円347円261円273円345円222円214円 OOP/6. 347円261円273円347円232円204円350円256円276円350円256円241円.ipynb" @@ -4,13 +4,13 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Python 和 OOP \n", + "# 1. Python 和 OOP \n", "Python 和 OOP 实现可以概括为三个概念:\n", "- **继承。**基于 Python 中的属性查找(在 X.name 表达式中)。\n", "- **多态。**在 X.method 方法中,method 的意义取决于 X 的类型(类)。\n", "- **封装。**方法和运算符实现行为,数据隐藏默认是一种惯例。\n", "\n", - "# OOP 和 继承:"Is-a" 关系 \n", + "# 2. OOP 和 继承:"Is-a" 关系 \n", "以制作比萨的机器人为例。"是一个"(is-a)关系:机器人是一个主厨,主厨是一个员工:" ] }, @@ -80,7 +80,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# OOP 和 组合:"Has-a" 关系 \n", + "# 3. OOP 和 组合:"Has-a" 关系 \n", "组合类一般都提供自己的接口,并通过内嵌的对象来实现接口。比萨店是一个组合对象,有烤炉,也有服务生和主厨。当顾客来店下单时,店里的组件就会开始行动:" ] }, @@ -149,7 +149,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# OOP 和委托:"包装"代理对象 \n", + "# 4. OOP 和委托:"包装"代理对象 \n", "委托通常就是指控制器对象内嵌其他对象,而把运算请求传给那些对象。控制器负责管理工作。在 Python 中,委托通常是以 `__getattr__` hook 方法实现的,因为这个方法会拦截对不存在属性的读取,"包装"类可以使用 `__getattr__` 把任意读取转发给被包装的对象。包装类包有被包装对象的接口,而且自己也可以增加其他运算。" ] }, @@ -251,17 +251,17 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 类的伪私有属性 \n", + "# 5. 类的伪私有属性 \n", "Python 支持变量名压缩(mangling)的概念,让类内某些变量局部化。压缩后的变量名有时会被误认为是"私有属性",但这只是一种把类所创建的变量名**局部化**的方式而已。这种功能主要是为了避免实例内的命名空间的冲突,而不是限制变量名的读取。 \n", "\n", "Python 程序员用一个单个的下划线来编写内部名称,这只是一个非正式的惯例。 \n", "\n", - "## 变量名压缩概览 \n", + "## 5.1 变量名压缩概览 \n", "class 语句内开头有两个下划线,但结尾没有两个下划线的变量名,会自动扩张,从而包含了所在类的名称。例如,Spam 类内 `__X` 这样的变量名会自动变成 `_Spam__X`:原始的变量名会在头部加入一个下划线,然后是所在类名称。因为修改后的变量名包含了所在类的名称,不会和同一层次中其他类所创建的类似变量名相冲突。 \n", "\n", "变量名压缩只发生在 class 语句内,而且只针对开头有两个下划线的变量名。 \n", "\n", - "## 为什么使用伪私有属性 \n", + "## 5.2 为什么使用伪私有属性 \n", "伪私有属性功能是为了缓和与实例属性储存方式有关的问题。在 Python 的类方法内,每当方法赋值 self 的属性时(例如,self.attr = value),就会在该实例内修改或创建该属性(继承搜索只发生在引用时,而不是赋值时)。如果在这个层次中有多个类赋值相同的属性,有可能发生冲突。" ] }, @@ -390,7 +390,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 方法是对象:绑定或无绑定 \n", + "# 6. 方法是对象:绑定或无绑定 \n", "类方法可以从一个实例或一个类访问,它们实际上在 Python 中有两种形式:\n", "- **无绑定类方法对象:无 self。**通过对类进行点号运算从而获取类的函数属性,会传回无绑定方法对象。调用该方法时,必须明确提供实例对象作为第一个参数。一个无绑定方法和一个简单的函数是相同的,可以通过类名来调用。\n", "- **绑定实例方法对象:self + 函数对。**通过对实例进行全运算从而获取类的函数属性,会传回绑定方法对象。Python 在绑定方法对象中自动把实例和函数打包,所以不用传递实例去调用该方法。" @@ -477,7 +477,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 在 Python 3.X 中,无绑定方法是函数 \n", + "## 6.1 在 Python 3.X 中,无绑定方法是函数 \n", "在 Python 3.X 中,已经删除了**无绑定方法**的概念。 \n", "\n", "在 Python 3.X 中,不使用一个实例而调用一个方法没有问题,只要这个方法不期待一个实例,并且通过类调用它而不是通过一个实例调用它。只有对通过实例调用,Python 3.X 才会向方法传递一个实例。当通过一个类调用时,只有在方法期待一个实例的时候,才必须手动传递一个实例:" @@ -598,7 +598,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 绑定方法和其他可调用对象 \n", + "## 6.2 绑定方法和其他可调用对象 \n", "绑定方法可以作为一个通用对象处理,可以任意地在一个程序中传递:" ] }, @@ -727,7 +727,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 类是对象:通用对象工厂 \n", + "# 7. 类是对象:通用对象工厂 \n", "有时候,基于类的设计要求要创建的对象来响应条件,而这些条件是在编写程序的时候无法预料的。工厂设计模式允许这样的一种延迟方法。\n", "\n", "可以将类传递给函数,这种函数在 OOP 设计中有时称为工厂。" @@ -826,7 +826,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 为什么使用工厂函数? \n", + "## 7.1 为什么使用工厂函数? \n", "通常来说,工厂函数可以使代码和动态配置对象构建的细节隔离开来。 \n", "\n", "在动态世界,我们可能不能硬编码流接口对象,而是根据配置文件的内容在运行时创建。 " @@ -836,14 +836,14 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 多重继承:"混合"类 \n", + "# 8. 多重继承:"混合"类 \n", "在 class 语句中,首行括号内可以列出一个以上的超类。当这么做时,就是在使用所谓的**多重继承**。 \n", "\n", "搜索属性时,Python 会由左至右搜索类首行中的超类,直到找到相符者。 \n", "\n", "当多个超类中有相同方法名时,会产生冲突,默认的继承通过 self.method() 会选择第一个出现的属性;也可以显式选择一个属性,通过引用类名 superclass.method(self)。 \n", "\n", - "## 编写混合显示类 \n", + "## 8.1 编写混合显示类 \n", "运算符重载中可以提供一个 `__str__` 或 `__repr__` 方法,以实现制定后的字符串表达形式。如果不在每个想打印的类中编写 `__repr__`,可以在一个通用工具类中编写一次,然后在所有的类中继承。 \n", "\n", "**用 `__dict__` 列出实例属性**" @@ -1042,7 +1042,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.5" + "version": "3.6.8" } }, "nbformat": 4, diff --git "a/Learning Python/6343円200円201円347円261円273円345円222円214円 OOP/7. 347円261円273円347円232円204円351円253円230円347円272円247円344円270円273円351円242円230円.ipynb" "b/Learning Python/6343円200円201円347円261円273円345円222円214円 OOP/7. 347円261円273円347円232円204円351円253円230円347円272円247円344円270円273円351円242円230円.ipynb" index 2dccc17..848da77 100644 --- "a/Learning Python/6343円200円201円347円261円273円345円222円214円 OOP/7. 347円261円273円347円232円204円351円253円230円347円272円247円344円270円273円351円242円230円.ipynb" +++ "b/Learning Python/6343円200円201円347円261円273円345円222円214円 OOP/7. 347円261円273円347円232円204円351円253円230円347円272円247円344円270円273円351円242円230円.ipynb" @@ -4,8 +4,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 扩展内置类型 \n", - "## 通过嵌入扩展类型 \n", + "# 1. 扩展内置类型 \n", + "## 1.1 通过嵌入扩展类型 \n", "这个类允许我们创建多个自包含的集合对象,带有预先设置的数据和行为,而不是手动把列表传入函数中:" ] }, @@ -78,7 +78,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 通过子类扩展类型 \n", + "## 1.2 通过子类扩展类型 \n", "所有内置类型都能直接创建子类,像 list、str、dict 以及 tuple 等类型转换函数都变成内置类型的名称。 \n", "\n", "可以编写自己的子类,定制列表偏移值以 1 开始计算:" @@ -131,8 +131,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 新式类的扩展 \n", - "## slots 实例 \n", + "# 2. 新式类的扩展 \n", + "## 2.1 slots 实例 \n", "将字符串属性名称顺序赋值给特殊的 `__slots__` 类属性,新式类就有可能既限制类的实例将有的合法属性集,又能够优化内存和速度性能。 \n", "\n", "只有 `__slots__` 列表内的变量名可赋值为实例属性,实例属性名必须在引用前赋值:" @@ -622,7 +622,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 特性:属性访问 \n", + "## 2.2 特性:属性访问 \n", "特性(property)提供另一种方式让新式类定义自动调用的方法,来读取或赋值实例属性。 \n", "\n", "尽管特性不支持通用属性路由路由目标,至少在特定属性上是 `__getattr__` 和 `__setattr__` 重载方法的替代做法。特性和这两个方法有类似效果,但是只在读取所需要的动态计算的变量名时,才会发生额外的方法调用。 \n", @@ -809,7 +809,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## `__getattribute__` 和描述符:属性工具 \n", + "## 2.3 `__getattribute__` 和描述符:属性工具 \n", "`__getattribute__` 方法只适用于新式类,可以让类拦截**所有**属性的引用,而不局限于未定义的引用。 \n", "\n", "Python 支持属性**描述符**的概念——带有 `__get__` 和 `__set__` 方法的类,分配给类属性并且由实例继承,这拦截了对特定属性的读取和写入访问。描述符在某种意义上是特性的一种更加通用的形式。实际上,特性是定义特定类型描述符的一种简化方式,该描述符运行关于访问的函数。" @@ -819,12 +819,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 静态方法和类方法 \n", + "# 3. 静态方法和类方法 \n", "有两种可以在类中定义不需要实例就可以调用的方法:**静态**方法大致类似于类中简单的无实例函数,**类**方法传递一个类而不是一个实例。 \n", "\n", "要启用这些方法模式,必须在类中调用特殊的内置函数 staticmethod 和 classmethod,或者使用特殊的 @name 装饰语法来调用它们。在 Python 3.X 中,对于仅通过类名调用的非实例方法,不需要 staticmethod 声明,但是如果通过实例调用此类方法,则仍然需要静态方法声明。 \n", "\n", - "## 为什么使用特殊的方法? \n", + "## 3.1 为什么使用特殊的方法? \n", "类的方法通常在第一个参数中传递一个实例对象,作为方法调用的隐含主体——这是"面向对象编程"中的"对象"。如今有两种方法可以改变这种模式。 \n", "\n", "有时,程序需要处理与类相关的数据,而不是实例。信息通常存储在类本身中,并在任何实例之外进行处理。 \n", @@ -835,7 +835,7 @@ "\n", "虽然不太常用,但 Python 也支持**类方法**的概念——这是类的一种方法,传递给它们的第一个参数是一个类对象而不是一个实例,不管它们是通过实例还是类调用。即使是通过实例调用,这样的方法可以通过 self 类参数访问类数据。常规方法(现在正规的叫法是**实例方法**)在调用时仍然接收一个主题实例,静态方法和类方法则不会。 \n", "\n", - "## Python 3.X 中的静态方法 \n", + "## 3.2 Python 3.X 中的静态方法 \n", "- 当通过实例获取方法时,生成一个绑定方法。\n", "- 从一个类获取一个方法会产生一个**简单函数**,没有给出实例也可以常规地调用。\n", "- 如果方法只通过一个类调用的话,我们不需要将这样的方法声明为静态的,但是,要通过一个实例调用它,我们必须这么做。" @@ -893,7 +893,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 使用静态和类方法 " + "## 3.3 使用静态和类方法 " ] }, { @@ -1037,7 +1037,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 使用静态方法统计实例 " + "## 3.4 使用静态方法统计实例 " ] }, { @@ -1106,7 +1106,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 用类方法统计实例 " + "## 3.5 用类方法统计实例 " ] }, { @@ -1202,7 +1202,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 装饰器和元类:第一部分 \n", + "# 4. 装饰器和元类:第一部分 \n", "Python **装饰器**提供了一个通用工具,用于添加管理函数和类的逻辑,或者稍后对它们的调用。 \n", "更具体地说,这实际上只是在函数和类定义时使用显式语法运行额外处理步骤的一种方式。它有两种方式:\n", "- 函数装饰器——它们为简单函数和类的方法指定了特殊的运算模式,将函数和类封装在一个额外的逻辑层中作为另一个函数实现,通常称为 metafunction。\n", @@ -1210,7 +1210,7 @@ "\n", "用户定义的函数装饰器通常写成类,把原始函数和其他数据当成状态信息。 \n", "\n", - "## 函数装饰器基础 \n", + "## 4.1 函数装饰器基础 \n", "函数装饰器是它后边的函数的运行时的声明。函数装饰器是写成一行,就在定义函数或方法的 def 语句之前,而且由 @ 符号、后面跟着**元函数(metafunction,管理另一函数(或其他可调用对象)的函数)**组成。静态方法可以用下面的装饰器语法编写:" ] }, @@ -1289,7 +1289,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 用户定义函数装饰器 " + "## 4.2 用户定义函数装饰器 " ] }, { @@ -1349,7 +1349,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 类装饰器和元类 \n", + "## 4.3 类装饰器和元类 \n", "**类装饰器**类似于函数装饰器,但是,它们在一条 class 语句的末尾运行,并且把一个类名重新绑定到一个可调用对象。它们可以用来管理类,或者当随后创建实例的时候插入一个包装逻辑层来管理实例:" ] }, @@ -1423,8 +1423,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# super 内置函数 \n", - "## 传统超类调用形式:便携、通用 \n", + "# 5. super 内置函数 \n", + "## 5.1 传统超类调用形式:便携、通用 \n", "在需要时通过显式地命名超类来调用超类方法,这种技术在 Python 中是传统的:" ] }, @@ -1460,7 +1460,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 基本 super 用法 " + "## 5.2 基本 super 用法 " ] }, { @@ -1504,7 +1504,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## super 的优点 \n", + "## 5.3 super 的优点 \n", "- 在运行时更改类树\n", "- 协同多重继承方法调度\n", "\n", @@ -1629,19 +1629,26 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 类陷阱 \n", - "## 修改类属性的副作用 \n", + "# 6. 类陷阱 \n", + "## 6.1 修改类属性的副作用 \n", "在类主体中,对变量名的赋值语句会产生属性,在运行时存在于类的对象内,而且会由所有实例继承。在 class 语句外动态修改类属性时,也会修改每个对象从该类继承而来的这个属性。 \n", "\n", - "## 修改可变的类属性也可能产生副作用 \n", + "## 6.2 修改可变的类属性也可能产生副作用 \n", "如果一个类属性引用一个可变对象,那么从任何实例在原处修改该对象都会立刻影响到所有实例。 \n", "\n", - "## 多重继承:顺序很重要 \n", + "## 6.3 多重继承:顺序很重要 \n", "Python 总是会根据超类在首行的顺序,从左至右搜索超类。 \n", "\n", - "## 过度包装 \n", + "## 6.4 过度包装 \n", "如果类层次太深,程序就变得晦涩难懂。" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { @@ -1660,7 +1667,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.5" + "version": "3.6.8" } }, "nbformat": 4, diff --git "a/Learning Python/6343円200円201円347円261円273円345円222円214円 OOP/8. 346円226円260円347円211円271円346円200円247円.ipynb" "b/Learning Python/6343円200円201円347円261円273円345円222円214円 OOP/8. 346円226円260円347円211円271円346円200円247円.ipynb" index 999a340..621f35e 100644 --- "a/Learning Python/6343円200円201円347円261円273円345円222円214円 OOP/8. 346円226円260円347円211円271円346円200円247円.ipynb" +++ "b/Learning Python/6343円200円201円347円261円273円345円222円214円 OOP/8. 346円226円260円347円211円271円346円200円247円.ipynb" @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Dataclass \n", + "# 1. Dataclass \n", "传统面向对象编程如下所示:" ] }, @@ -96,7 +96,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.5" + "version": "3.6.8" } }, "nbformat": 4, From 5958183ab02053184308465b5c6dbe5940628e1f Mon Sep 17 00:00:00 2001 From: Lanxin <675579465@qq.com> Date: 2019年9月30日 14:50:13 +0800 Subject: [PATCH 5/7] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=BC=82=E5=B8=B8?= =?UTF-8?q?=E5=92=8C=E5=B7=A5=E5=85=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...345270円270円345円237円272円347円241円200円.ipynb" | 16 ++++----- ...347240円201円347円273円206円350円212円202円.ipynb" | 36 +++++++++---------- ...345270円270円345円257円271円350円261円241円.ipynb" | 20 +++++------ ...347232円204円350円256円276円350円256円241円.ipynb" | 34 +++++++++--------- 4 files changed, 53 insertions(+), 53 deletions(-) diff --git "a/Learning Python/7343円200円201円345円274円202円345円270円270円345円222円214円345円267円245円345円205円267円/1. 345円274円202円345円270円270円345円237円272円347円241円200円.ipynb" "b/Learning Python/7343円200円201円345円274円202円345円270円270円345円222円214円345円267円245円345円205円267円/1. 345円274円202円345円270円270円345円237円272円347円241円200円.ipynb" index a0d5e0e..da1e325 100644 --- "a/Learning Python/7343円200円201円345円274円202円345円270円270円345円222円214円345円267円245円345円205円267円/1. 345円274円202円345円270円270円345円237円272円347円241円200円.ipynb" +++ "b/Learning Python/7343円200円201円345円274円202円345円270円270円345円222円214円345円267円245円345円205円267円/1. 345円274円202円345円270円270円345円237円272円347円241円200円.ipynb" @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 异常的角色 \n", + "# 1. 异常的角色 \n", "在 Python 中,异常通常可用于各种用途:\n", "- **错误处理。**每当在运行时检测到程序错误时,Python 就会引发异常。可以在程序代码中捕捉和响应错误,或者忽略已发生的异常。如果忽略错误,Python 默认的异常处理行为将启动:停止程序,打印出错消息。如果不想启动这种默认行为,就要写 try 语句来捕捉异常并从异常中恢复。\n", "- **事件通知。**异常也可用于发出有效状态的信号,而不需在程序间传递结果标志位,或者刻意对其进行测试。\n", @@ -17,8 +17,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 异常处理 \n", - "## 默认异常处理器 \n", + "# 2. 异常处理 \n", + "## 2.1 默认异常处理器 \n", "当代码没有捕获异常时,它会一直向上返回到程序顶层,并启用默认的异常处理器,打印标准出错信息。" ] }, @@ -52,7 +52,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 捕获异常 \n", + "## 2.2 捕获异常 \n", "如果不想要默认的异常行为,就需要把调用包装在 try 语句内,自行捕捉异常:" ] }, @@ -112,7 +112,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 引发异常 \n", + "## 2.3 引发异常 \n", "异常能由 Python 或程序引发,也能捕捉或忽略。要手动触发异常,直接执行 raise 语句:" ] }, @@ -141,7 +141,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 用户定义的异常 \n", + "## 2.4 用户定义的异常 \n", "用户定义的异常能够通过类编写,它继承自一个内置的异常类:通常这个类的名称叫做 Exception。基于类的异常允许脚本建立异常类型、继承行为以及附加状态信息:" ] }, @@ -174,7 +174,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 终止行为 \n", + "## 2.5 终止行为 \n", "try 语句可以包含 finally 代码块,可以定义一定会在最后执行时的收尾行为,无论 try 代码块中是否发生了异常:" ] }, @@ -215,7 +215,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.5" + "version": "3.6.8" } }, "nbformat": 4, diff --git "a/Learning Python/7343円200円201円345円274円202円345円270円270円345円222円214円345円267円245円345円205円267円/2. 345円274円202円345円270円270円347円274円226円347円240円201円347円273円206円350円212円202円.ipynb" "b/Learning Python/7343円200円201円345円274円202円345円270円270円345円222円214円345円267円245円345円205円267円/2. 345円274円202円345円270円270円347円274円226円347円240円201円347円273円206円350円212円202円.ipynb" index c2fe2f8..83b7a7d 100644 --- "a/Learning Python/7343円200円201円345円274円202円345円270円270円345円222円214円345円267円245円345円205円267円/2. 345円274円202円345円270円270円347円274円226円347円240円201円347円273円206円350円212円202円.ipynb" +++ "b/Learning Python/7343円200円201円345円274円202円345円270円270円345円222円214円345円267円245円345円205円267円/2. 345円274円202円345円270円270円347円274円226円347円240円201円347円273円206円350円212円202円.ipynb" @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# try/except/else 语句 \n", + "# 1. try/except/else 语句 \n", "try 是复合语句,它的最完整的形式如下:" ] }, @@ -32,12 +32,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 语句的运行方式 \n", + "## 1.1 语句的运行方式 \n", "- 如果 try 代码块语句执行时的确发生了异常,Python 就跳回 try,执行第一个符合引发异常的 except 子句下面的语句。当 except 代码块执行后,控制权就会到整个 try 语句后继续执行。\n", "- 如果异常发生在 try 代码块内,没有符合的 except 子句,异常就会向上传递到程序中的之前进入的 try 中,或者如果它是第一条这样的语句,就传递到这个进程的顶层,Python 会终止程序并打印默认出错消息。\n", "- 如果 try 首行底下执行的语句没有发生异常,Python 就会执行 else 行下的语句,控制权会在整个 try 语句下继续。\n", "\n", - "## try 语句分句 \n", + "## 1.2 try 语句分句 \n", "分句形式|说明\n", ":---|:---\n", "except:|捕捉所有(其他)异常类型\n", @@ -69,7 +69,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## try/else 分句 \n", + "## 1.3 try/else 分句 \n", "没有 else,是无法知道控制流程是否已经通过了 try 语句,因为没有异常引发或者因为异常发生了且已被处理过。" ] }, @@ -77,7 +77,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# try/finally 语句 \n", + "# 2. try/finally 语句 \n", "- 如果 try 代码块运行时没有异常发生,Python 会跳至执行 finally 代码块,然后在整个 try 语句后继续执行下去。\n", "- 如果 try 代码块运行时有异常发生,Python 依然会回来运行 finally 代码块,但是接着会把异常向上传递到较高的 try 语句或顶层默认处理器。程序不会在 try 语句下继续运行。\n", "\n", @@ -88,7 +88,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 统一 try/except/finally 语句 \n", + "# 3. 统一 try/except/finally 语句 \n", "```\n", "try:\n", " main-action\n", @@ -105,7 +105,7 @@ "\n", "即使异常处理器或者 else-block 内有错误发生而引发了新的异常,finally-block 内的程序代码依然会执行。 \n", "\n", - "## 统一 try 语句语法 \n", + "## 3.1 统一 try 语句语法 \n", "方括号表示可选,星号表示0个或多个:\n", "```\n", "# format1\n", @@ -134,10 +134,10 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# raise 语句 \n", + "# 4. raise 语句 \n", "要显式地触发异常,可以使用 raise 语句。raise 关键字,后面跟着可选的要引发的类或者类的一个实例。 \n", "\n", - "## 引发异常 \n", + "## 4.1 引发异常 \n", "对于内置异常,如下两种形式是对等的,都会引发指定的异常类的一个实例,但是第一种形式隐式地创建实例:" ] }, @@ -210,7 +210,7 @@ "\n", "一旦异常在程序中某处由一条 except 子句捕获,它就死掉了,除非由另一个 raise 语句或错误重新引发它。 \n", "\n", - "## 利用 raise 传递异常 \n", + "## 4.2 利用 raise 传递异常 \n", "raise 语句不包括异常名称或额外数据值时,就是重新引发当前异常。如果需要捕捉和处理一个异常,又不希望异常在程序代码中死掉,一般就会使用这种形式:" ] }, @@ -257,7 +257,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Python 3.X 异常链:raise from \n", + "## 4.3 Python 3.X 异常链:raise from \n", "Python 3.X 允许 raise 语句拥有一个可选的 from 子句:\n", "```\n", "raise exception from otherexception\n", @@ -297,14 +297,14 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# assert 语句 \n", + "# 5. assert 语句 \n", "assert 语句是 raise 常见使用模式的语法简写,assert 可视为条件式的 raise 语句:\n", "```\n", "assert , \n", "```\n", "如果 test 计算为假,Python 就会引发异常:data 项(如果提供了的话)是异常的额外数据。 \n", "\n", - "## 例子:收集约束条件(但不是错误) \n", + "## 5.1 例子:收集约束条件(但不是错误) \n", "assert 语句通常用于验证开发期间程序的状况。显示时,其出错消息正文会自动包括源代码的行信息,以及列在 assert 语句中的值:" ] }, @@ -371,17 +371,17 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# with/as 环境管理器 \n", + "# 6. with/as 环境管理器 \n", "with/as 语句是作为常见 try/finally 用法模式的替代方案。with 语句支持更丰富的基于对象的协议,可为代码块定义支持进入和离开的动作。 \n", "\n", - "## 基本使用 \n", + "## 6.1 基本使用 \n", "```\n", "with expression [as variable]:\n", " with-block\n", "```\n", "expression 要返回一个对象,此对象也可返回一个值,赋值给变量名 variable。 \n", "\n", - "## 环境管理协议 \n", + "## 6.2 环境管理协议 \n", "with 语句实际工作方式:\n", "1. 计算表达式,所得到的对象称为环境管理器,它必须有 `__enter__` 和 `__exit__` 方法。\n", "2. 环境管理器的 `__enter__` 方法会被调用。如果 as 子句存在,其返回值会赋值给 As 子句中的变量,否则,直接丢弃。\n", @@ -389,7 +389,7 @@ "4. 如果 with 代码块引发异常,`__exit__`(type, value, traceback) 方法就会被调用。这些也是由 sys.exc_info 返回的相同值。如果此方法返回值为假,则异常会重新引发。否则,异常会终止。正常情况下异常是应该被重新引发,这样的话才能传递到 with 语句之外。\n", "5. 如果 with 代码块没有引发异常,`__exit__` 方法依然会被调用,其 type、value 以及 traceback 参数都会以 None 传递。 \n", "\n", - "## 多环境管理器 \n", + "## 6.3 多环境管理器 \n", "with 语句可以使用新的逗号语法指定多个环境管理器:" ] }, @@ -422,7 +422,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.5" + "version": "3.6.8" } }, "nbformat": 4, diff --git "a/Learning Python/7343円200円201円345円274円202円345円270円270円345円222円214円345円267円245円345円205円267円/3. 345円274円202円345円270円270円345円257円271円350円261円241円.ipynb" "b/Learning Python/7343円200円201円345円274円202円345円270円270円345円222円214円345円267円245円345円205円267円/3. 345円274円202円345円270円270円345円257円271円350円261円241円.ipynb" index 138b31f..9352c76 100644 --- "a/Learning Python/7343円200円201円345円274円202円345円270円270円345円222円214円345円267円245円345円205円267円/3. 345円274円202円345円270円270円345円257円271円350円261円241円.ipynb" +++ "b/Learning Python/7343円200円201円345円274円202円345円270円270円345円222円214円345円267円245円345円205円267円/3. 345円274円202円345円270円270円345円257円271円350円261円241円.ipynb" @@ -9,8 +9,8 @@ "- **它们附加了状态信息。**\n", "- **它们支持继承。**\n", "\n", - "# 异常:回到未来 \n", - "## 编写异常类 " + "# 1. 异常:回到未来 \n", + "## 1.1 编写异常类 " ] }, { @@ -57,7 +57,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 为什么使用类异常 \n", + "# 2. 为什么使用类异常 \n", "把库的异常安排到类树中,有个共同的超类来包装整个类型。这样,用户只需列出共同的超类,来捕捉库的所有异常。" ] }, @@ -65,14 +65,14 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 内置 Exception 类 \n", + "# 3. 内置 Exception 类 \n", "Python 把内置异常组织成层次,来支持各种捕捉模式。 \n", "**BaseException。**异常的顶级根类。这个类不能当作是由用户定义的类直接继承的(使用 Exception)。它提供了子类所继承的默认的打印和状态保持行为。 \n", "**Exception。**与应用相关的异常的顶层根超类。是所有其他内置异常的超类,除了系统推出事件类之外。 \n", "**ArithmeticError。**所有数值错误的超类。 \n", "**OverflowError。**识别特定的数值错误的子类。 \n", "\n", - "## 默认打印和状态 \n", + "## 3.1 默认打印和状态 \n", "内置异常还提供了默认打印显示和状态保持。传递给这些类的任何构造函数参数都会保存在实例的 args 元组属性中,并且当打印该实例的时候自动显示,对于用户定义的异常也是如此:" ] }, @@ -143,7 +143,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 定制打印显示 \n", + "# 4. 定制打印显示 \n", "可以在类中定义两个字符串表示重载方法中的一个(`__repr__` 或 `__str__`),来返回想要为异常显示的字符串:" ] }, @@ -196,8 +196,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 定制数据和行为 \n", - "## 提供异常细节 \n", + "# 5. 定制数据和行为 \n", + "## 5.1 提供异常细节 \n", "当引发一个异常的时候,可能会跨越任意的文件界限——触发异常的 raise 语句和捕获异常的 try 语句可能位于完全不同的模块文件中。在异常自身中传递额外的状态信息,这允许 try 语句更可靠地访问它。 " ] }, @@ -233,7 +233,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 提供异常方法 \n", + "## 5.2 提供异常方法 \n", "异常类也可以定义在处理器中调用的方法:" ] }, @@ -281,7 +281,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.5" + "version": "3.6.8" } }, "nbformat": 4, diff --git "a/Learning Python/7343円200円201円345円274円202円345円270円270円345円222円214円345円267円245円345円205円267円/4. 345円274円202円345円270円270円347円232円204円350円256円276円350円256円241円.ipynb" "b/Learning Python/7343円200円201円345円274円202円345円270円270円345円222円214円345円267円245円345円205円267円/4. 345円274円202円345円270円270円347円232円204円350円256円276円350円256円241円.ipynb" index 9f3a413..a81d821 100644 --- "a/Learning Python/7343円200円201円345円274円202円345円270円270円345円222円214円345円267円245円345円205円267円/4. 345円274円202円345円270円270円347円232円204円350円256円276円350円256円241円.ipynb" +++ "b/Learning Python/7343円200円201円345円274円202円345円270円270円345円222円214円345円267円245円345円205円267円/4. 345円274円202円345円270円270円347円232円204円350円256円276円350円256円241円.ipynb" @@ -4,12 +4,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 嵌套异常处理器 \n", + "# 1. 嵌套异常处理器 \n", "try 语句可以嵌套,当 try/except 语句发生异常时,Python 会回到最近进入、具有相符 except 分句的 try 语句。一旦异常被捕捉,其生命就结束,控制权不会跳回所有匹配这个异常、相符的 try 语句;只有第一个 try 有机会对它进行处理。 \n", "\n", "当 try/finally 语句嵌套且发生异常时,每个 finally 代码块都会执行,Python 会持续把异常往上传递到其他 try 语句上,最终可能达到顶层默认处理器,除非有个 try/except 在这个过程中捕捉某处该异常。 \n", "\n", - "## 例子:控制流程嵌套 " + "## 1.1 例子:控制流程嵌套 " ] }, { @@ -45,7 +45,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 例子:语法嵌套化 " + "## 1.2 例子:语法嵌套化 " ] }, { @@ -82,8 +82,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 异常的习惯用法 \n", - "## 跳出多重嵌套循环:"go to" \n", + "# 2. 异常的习惯用法 \n", + "## 2.1 跳出多重嵌套循环:"go to" \n", "异常经常被用来作为其他语言的"go to"语句来实现任意控制转移。raise 相当于"go to",except 子句和异常名称作为程序标签。" ] }, @@ -130,11 +130,11 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 异常不总是错误 \n", + "## 2.2 异常不总是错误 \n", "内置的 input 函数在每次调用时,在文件末尾时引发内置的 EOFError。 \n", "调用 sys.exit() 并在键盘上按下 Ctrl-C,会分别引发 SystemExit 和 KeyboardInterrupt。 \n", "\n", - "## 函数通过 raise 表示状态 \n", + "## 2.3 函数通过 raise 表示状态 \n", "用户定义的异常也可引发非错误的情况:" ] }, @@ -164,8 +164,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 关闭文件和服务器连接 \n", - "## 在 try 外进行调试 \n" + "## 2.4 关闭文件和服务器连接 \n", + "## 2.5 在 try 外进行调试 \n" ] }, { @@ -192,7 +192,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 运行进程中的测试 " + "## 2.6 运行进程中的测试 " ] }, { @@ -219,7 +219,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 关于 sys.exc_info \n", + "## 2.7 关于 sys.exc_info \n", "通常允许一个异常处理器获取对最近引发的异常的访问。如果没有处理器正在处理,就返回包含了三个 None 值的元组。否则,将会返回(type、value 和 traceback):\n", "- type:正在处理的异常的异常类型\n", "- value:引发的异常类实例\n", @@ -227,7 +227,7 @@ "\n", "sys.exc_info 主要由空的 except 使用。 \n", "\n", - "## 显示错误和跟踪信息 " + "## 2.8 显示错误和跟踪信息 " ] }, { @@ -282,15 +282,15 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 异常设计技巧和陷阱 \n", - "## 应该包装什么 \n", + "# 3. 异常设计技巧和陷阱 \n", + "## 3.1 应该包装什么 \n", "- 经常会失败的运算一般都应该包装在 try 语句内。例如,和系统状态衔接的运算(文件开启、套接字调用等)就是 try 的主要候选者。\n", "- 在简单的脚本中,你会希望这类运算失败时终止程序,而不是被捕捉或是被忽略。Python 中的错误会产生有用的出错消息,而且这通常就是所期望的最好结果。\n", "- 应该在 try/finally 中实现终止动作,从而保证它们的执行。\n", "- 偶尔,把对大型函数的调用包装在单个 try 语句内,而不是让函数本身零散着放入若干 try 语句中。\n", "\n", - "## 捕捉太多:避免空 except 语句 \n", - "## 捕捉过少:使用基于类的分类 " + "## 3.2 捕捉太多:避免空 except 语句 \n", + "## 3.3 捕捉过少:使用基于类的分类 " ] }, { @@ -333,7 +333,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.5" + "version": "3.6.8" } }, "nbformat": 4, From cc21120a952f7902c27de806d331f4f5095f6d5f Mon Sep 17 00:00:00 2001 From: Lanxin <675579465@qq.com> Date: 2019年9月30日 14:58:47 +0800 Subject: [PATCH 6/7] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E9=AB=98=E7=BA=A7?= =?UTF-8?q?=E8=AF=9D=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...345255円227円347円254円246円344円270円262円.ipynb" | 62 +++++++++---------- ...347220円206円345円261円236円346円200円247円.ipynb" | 52 ++++++++-------- ...350243円205円351円245円260円345円231円250円.ipynb" | 40 ++++++------ .../4. 345円205円203円347円261円273円.ipynb" | 54 ++++++++-------- 4 files changed, 104 insertions(+), 104 deletions(-) diff --git "a/Learning Python/8343円200円201円351円253円230円347円272円247円350円257円235円351円242円230円/1. Unicode 345円222円214円345円255円227円350円212円202円345円255円227円347円254円246円344円270円262円.ipynb" "b/Learning Python/8343円200円201円351円253円230円347円272円247円350円257円235円351円242円230円/1. Unicode 345円222円214円345円255円227円350円212円202円345円255円227円347円254円246円344円270円262円.ipynb" index 62767e5..12b1616 100644 --- "a/Learning Python/8343円200円201円351円253円230円347円272円247円350円257円235円351円242円230円/1. Unicode 345円222円214円345円255円227円350円212円202円345円255円227円347円254円246円344円270円262円.ipynb" +++ "b/Learning Python/8343円200円201円351円253円230円347円272円247円350円257円235円351円242円230円/1. Unicode 345円222円214円345円255円227円350円212円202円345円255円227円347円254円246円344円270円262円.ipynb" @@ -4,8 +4,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 字符串基础知识 \n", - "## 字符编码方法 \n", + "# 1. 字符串基础知识 \n", + "## 1.1 字符编码方法 \n", "大多数程序员把字符串看作是用来表示文本数据的一系列字符。但是,根据必须记录何种字符集,计算机内存中存储字符的方式有所不同。 \n", "\n", "ASCII 标准在美国创建,并且定义了大多数美国程序员使用的文本字符串表示法。ASCII 定义了从0到127的字符代码,并且允许每个字符存储在一个8位的字节中(实际上,只有其中的7位真正用到)。例如,ASCII 标准把字符 'a' 映射为整数值 97 (十六进制中的0x61),它存储在内存和文件的一个单个字节中:" @@ -141,7 +141,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Python 如何在内存中存储字符串 \n", + "## 1.2 Python 如何在内存中存储字符串 \n", "前一节的编码实际上只适用于文本存储或传输到外部的文件和其他媒介中。在内存中,Python 总是以与编码无关的格式存储解码的文本字符串,对于每个字符,它可能使用或不使用多个字节。所有文本处理都以这种统一的内部格式进行。只有当被传输到或传输自外部文本文件、字节字符串或有特定编码需求的 API 时,文本才会被转换为特定的编码格式。然而,一旦在内存中,字符串就没有编码。它们只是本书中介绍的字符串对象。 \n", "\n", "Python 3.3 和更高版本使用的是可变长度方案,每个字符有 1、2 或 4 字节,具体取决于字符串的内容。大小是根据字符串中 Unicode 序号最大的字符来选择的。这种方案在通常情况下允许节省空间,但也允许在所有平台上使用完整的 UCS-4。 " @@ -151,7 +151,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Python 字符串类型 \n", + "## 1.3 Python 字符串类型 \n", "Python 语言提供了字符串数据类型在脚本中表示字符文本。Python 3.X 带有 3 种字符串对象类型——一种用于文本数据,两种用于二进制数据:\n", "- `str` 表示 Unicode 文本(8位的和更宽的)。\n", "- `bytes` 表示二进制数据。\n", @@ -173,7 +173,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 文本和二进制文件 \n", + "## 1.4 文本和二进制文件 \n", "文件 I/O(输入和输出)在 Python 3 中也有所改进,以反映 str/bytes 的区分以及对编码 Unicode 文本的自动支持。Python 现在在文本文件和二进制文件之间做了一个明显的独立于平台的区分:\n", "- 文本文件\n", " - 当一个文件以文本模式打开的时候,读取其数据会自动将其内容解码(每个平台一个默认的或一个提供的编码名称),并且将其返回为一个 `str` ,写入会接受一个 `str`,并且在将其传输到文件之前自动编码它。文本模式的文件还支持统一的行尾转换和额外的编码特定参数。根据编码名称,文本文件也自动处理文件开始处的字节顺序标记序列。\n", @@ -189,8 +189,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Python 的字符串应用 \n", - "## 字符串常量 \n", + "# 2. Python 的字符串应用 \n", + "## 2.1 字符串常量 \n", "当调用 `str` 或 `bytes` 这样的一个内置函数、通过调用 `open` 创建读取一个文件或在脚本中编写常量语法时,会引发 Python 3 的字符串对象。对于后者,一种新的常量形式 `b'xxx'`(以及对等的 `B'xxx'`)用来创建 Python 3 中的 `bytes` 对象,`bytearray` 对象可以通过调用 `bytearray` 函数来创建,这会带有各种可能的参数。 \n", "\n", "在 Python 3 中,所有当前字符串常量形式,'xxx'、\"xxx\" 和三引号字符串块,都产生一个 `str`;在它们任何一种前面添加一个 `b` 或 `B` ,则会创建一个 `bytes`。这个新的 `b'...'` 字节常量类似于用来抑制反斜杠转义的 `r'...'` raw字符串。" @@ -369,7 +369,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 字符串类型转换 \n", + "## 2.2 字符串类型转换 \n", "Python 3 中 `str` 和 `bytes` 类型对象不在表达式中自动地混合,并且当传递给函数的时候不会自动地相互转换。期待一个 `str` 对象作为参数的函数,通常不能接受一个 `bytes` ;反之亦然。 \n", "\n", "因此,Python 3 基本上要求遵守一种类型或另一种类型,或者手动执行显式转换:\n", @@ -596,10 +596,10 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 编码 Unicode 字符串 \n", + "# 3. 编码 Unicode 字符串 \n", "要在字符串中编码任意的 Unicode 字符,有些字符可能甚至无法在键盘上输入,Python 的字符串常量支持 \"\\xNN\" 十六进制字节值转义以及 \"\\uNNNN\" 和 \"\\UNNNNNNNN\" Unicode 转义。 \n", "\n", - "## 编码 ASCII 文本 \n", + "## 3.1 编码 ASCII 文本 \n", "ASCII 文本是一种简单的 Unicode,存储为表示字符的字节值的一个序列:" ] }, @@ -668,7 +668,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 编码非 ASCII 文本 \n", + "## 3.2 编码非 ASCII 文本 \n", "要编码非 ASCII 字符,可能在字符串中使用十六进制或 Unicode 转义;十六进制转义限制于单个字节的值,但 Unicode 转义可以指定其值有两个和四个字节宽度的字符。也可以将其嵌入 Python 3 的 str 对象中:" ] }, @@ -779,7 +779,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 编码和解码非 ASCII 文本 \n", + "## 3.3 编码和解码非 ASCII 文本 \n", "如果我们试图把一个非 ASCII 字符串编码为 raw 字节以像 ASCII 一样使用,我们会得到一个错误,因为字符超出了 ASCII 的 7 位编码值范围:" ] }, @@ -925,7 +925,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 其他 Unicode 编码技术 \n", + "## 3.4 其他 Unicode 编码技术 \n", "一些编码甚至使用较大的字节序列来表示字符。当需要的时候,我们可以为自己字符串中的字符指定 16 位或 32 位的 Unicode 值,对于前者使用 `\"\\u...\"` 表示 4 个十六进制位,对于后者使用 `\"\\U....\"` 表示 8 个十六进制位。" ] }, @@ -994,7 +994,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 字节字符串常量:编码文本 \n", + "## 3.5 字节字符串常量:编码文本 \n", "这里有两点要注意。首先,Python 3 允许特殊的字符以十六进制和 Unicode 转义的方式编码到 `str` 字符串中,但是,只能以十六进制转义的方式编码到 `bytes` 字符串中:Unicode 转义会默默地逐字转换为字节常量,而不是转义。实际上,`bytes` 必须编码为 `str` 字符串,以便正常地打印非 ASCII 字符:" ] }, @@ -1252,7 +1252,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 转换编码 \n", + "## 3.6 转换编码 \n", "我们总是可以把一个字符串转换为不同于源字符集默认的一种编码,但是,我们必须显式地提供一个编码名称以进行编码和解码:" ] }, @@ -1350,7 +1350,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 源文件字符集编码声明 \n", + "## 3.7 源文件字符集编码声明 \n", "对于在脚本文件中编码的字符串,Python 默认地使用 UTF-8 编码,但是,它允许我们通过包含一个注释来指明想要的编码,从而将默认值修改为支持任意的字符集。这个注释必须拥有如下的形式,并且在 Python 中必须作为脚本的第一行或第二行出现:" ] }, @@ -1374,10 +1374,10 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 使用 Python 3.X bytes 对象 \n", + "# 4. 使用 Python 3.X bytes 对象 \n", "Python 3 bytes 对象是较小整数的一个序列,其中每个整数都在 0 到 255 之间,并且在显示的时候恰好打印为 ASCII 字符。 \n", "\n", - "## 方法调用 \n", + "## 4.1 方法调用 \n", "`bytes` 对象是不可改变的,就像是 Python 中的 `str` 对象一样:" ] }, @@ -1487,7 +1487,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 序列操作 \n", + "## 4.2 序列操作 \n", "如下的代码索引一个 `bytes` 对象并返回一个给出了该字节的二进制值的整数;`bytes` 实际上是 8 位整数的一个序列,但是,当作为整体显示的时候,为了方便起见,它打印为 ASCII 编码的字符的一个字符串。要查看一个给定的字节的值,使用 chr 内置函数来将其转换回字符:" ] }, @@ -1636,7 +1636,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 创建 bytes 对象的其他方式 \n", + "## 4.3 创建 bytes 对象的其他方式 \n", "可以用一个 `str` 和一个编码名来调用 `bytes` 构造函数,用一个可迭代的整数表示的字节值来调\n", "用 `bytes` 构造函数,或者按照每个默认(或传入的)编码来编码一个 `str` 对象,从而创建 `bytes` 对象:" ] @@ -1770,7 +1770,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 混合字符串类型 \n", + "## 4.4 混合字符串类型 \n", "在 `replace` 调用中,我们必须传入两个 `bytes` 对象,`str` 对象在这里无效。Python 3 需要在某些环境下要求特殊的字符串类型并且如果需要的话期待手动转换:" ] }, @@ -1943,10 +1943,10 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 使用 Python 3.X bytearray 对象 \n", + "# 5. 使用 Python 3.X bytearray 对象 \n", "Python 3 还有第三个字符串类型 `bytearray`,这是范围在 0 到 255 之间的整数的一个可变的序列,其本质是 `bytes` 的可变的变体。 \n", "\n", - "## bytearray 应用 \n", + "## 5.1 bytearray 应用 \n", "`bytearray` 需要一个编码名称和字节字符串,因为文本和二进制字符串不能混合:" ] }, @@ -2282,7 +2282,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Python 3.X 字符串类型总结 \n", + "## 5.2 Python 3.X 字符串类型总结 \n", "下面的例子展示了 `bytes` 和 `bytearray` 对象如何是 `int` 的序列,而 `str` 对象是字符的序列:" ] }, @@ -2381,11 +2381,11 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 使用文本文件和二进制文件 \n", + "# 6. 使用文本文件和二进制文件 \n", "- 文本模式文件 根据 Unicode 编码来解释文件内容,要么是平台的默认编码,要么是我们传递进的编码名。通过传递一个编码名来打开文件,我们可以强行进行 Unicode 文件的各种类型的转换。文本模型的文件也执行通用的行末转换:默认地,所有的行末形式映射为脚本中的一个单个的 '\\n' 字符,而不管在什么平台上运行。文本文件也负责阅读和写入在某些 Unicode 编码方案中存储文件开始处的**字节顺序标记**(Byte Order Mark,BOM)。\n", "- 二进制模式文件 不会返回**原始的**文件内容,而是作为表示字节值的整数的一个序列,没有编码或解码,也没有行末转换。\n", "\n", - "## Python 3.X 中的文本和二进制模式 " + "## 6.1 Python 3.X 中的文本和二进制模式 " ] }, { @@ -2529,7 +2529,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 类型和内容错误匹配 \n", + "## 6.2 类型和内容错误匹配 \n", "如果试图向一个文本文件写入一个 `bytes` 或者向二进制文件写入一个 `str` ,将会得到错误:" ] }, @@ -2626,10 +2626,10 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 使用 Unicode 文件 \n", + "# 7. 使用 Unicode 文件 \n", "Python 3 的 `open` 调用针对文本文件接受一个编码,在数据传输的时候,它自动为我们编码和解码。这允许我们处理用不同编码创建的 Unicode 文本,而不仅是平台默认编码的 Unicode 文本,并且以不同的编码存储以供转换。 \n", "\n", - "## 在 Python 3.X 中读取和写入 Unicode \n", + "## 7.1 在 Python 3.X 中读取和写入 Unicode \n", "有两种办法可以把字符串转换为不同的编码:用方法调用手动地转换和在文件输入输出上自动地转换。" ] }, @@ -2885,7 +2885,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Unicode 文件名和流 \n", + "## 7.2 Unicode 文件名和流 \n", "Python 也支持非 ASCII 文件名的概念。它们在 sys 中是独立的设置,每个 Python 版本和平台都可能不同:" ] }, @@ -2973,7 +2973,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.6" + "version": "3.6.8" } }, "nbformat": 4, diff --git "a/Learning Python/8343円200円201円351円253円230円347円272円247円350円257円235円351円242円230円/2. 347円256円241円347円220円206円345円261円236円346円200円247円.ipynb" "b/Learning Python/8343円200円201円351円253円230円347円272円247円350円257円235円351円242円230円/2. 347円256円241円347円220円206円345円261円236円346円200円247円.ipynb" index c235f90..bafe996 100644 --- "a/Learning Python/8343円200円201円351円253円230円347円272円247円350円257円235円351円242円230円/2. 347円256円241円347円220円206円345円261円236円346円200円247円.ipynb" +++ "b/Learning Python/8343円200円201円351円253円230円347円272円247円350円257円235円351円242円230円/2. 347円256円241円347円220円206円345円261円236円346円200円247円.ipynb" @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 为什么管理属性 \n", + "# 1. 为什么管理属性 \n", "通常,属性只是对象的名称" ] }, @@ -33,7 +33,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 插入在属性访问时运行的代码 \n", + "# 2. 插入在属性访问时运行的代码 \n", "一个更好的解决方案是,如果需要的话,在属性访问时自动运行代码。 \n", "- `__getattr__` 和 `__setattr__` 方法 ,把未定义的属性获取和所有的属性赋值指向通用的处理器方法。\n", "- `__getattribute__` 方法,把所有属性获取都指向 Python 的所有类中的一个泛型处理器方法。\n", @@ -45,7 +45,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 特性 \n", + "# 3. 特性 \n", "特性协议允许我们把一个特定属性的 get 和 set 操作指向我们所提供的函数或方法,使得我们能够插入在属性访问的时候自动运行的代码,拦截属性删除,还可为属性提供文档。 \n", "\n", "通过 `property` 内置函数来创建特性并将其分配给类属性,就像方法函数一样。 \n", @@ -56,7 +56,7 @@ "\n", "一个特性管理一个单个的、特定的属性。它允许我们控制访问的赋值操作,并且允许我们自由地把一个属性从简单的数据改变为一个计算,而不会影响已有的代码。 \n", "\n", - "## 基础知识 \n", + "## 3.1 基础知识 \n", "可以通过把一个内置函数的结果赋给一个类属性来创建一个特性:" ] }, @@ -88,7 +88,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 第一个例子 \n", + "## 3.2 第一个例子 \n", "使用一个特性来记录对一个名为 name 的属性的访问,实际存储的数据名为 \\_name" ] }, @@ -154,7 +154,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 计算的属性 \n", + "## 3.3 计算的属性 \n", "例如,当获取属性的时候,动态地计算属性的值。" ] }, @@ -203,7 +203,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 使用装饰器编写特性 \n", + "## 3.4 使用装饰器编写特性 \n", "内置函数 `property` 可以充当一个装饰器,来定义一个函数,当获取一个属性的时候自动运行该函数:" ] }, @@ -287,7 +287,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 描述符 \n", + "# 4. 描述符 \n", "描述符提供了拦截属性访问的一种替代方法。 \n", "\n", "特性是描述符的一种,从技术上讲,property 内置函数只是创建一个特定类型的描述符的一种简化方式,而这种描述符在属性访问时运行方法函数。 \n", @@ -296,7 +296,7 @@ "\n", "描述符作为独立的类创建。可以通过子类和实例继承。描述符提供了对获取和赋值访问的控制,并且允许我们自由地把简单的数据修改为计算值从而改变一个属性,而不会影响已有的代码。 \n", "\n", - "## 基础知识 " + "## 4.1 基础知识 " ] }, { @@ -574,7 +574,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 第一个示例" + "## 4.2 第一个示例" ] }, { @@ -674,7 +674,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 计算的属性 " + "## 4.3 计算的属性 " ] }, { @@ -720,7 +720,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 在描述符中使用状态信息 \n", + "## 4.4 在描述符中使用状态信息 \n", "- 描述符状态用来管理内部用于描述符工作的数据。\n", "- 实例状态记录了和客户类相关的信息,以及可能由客户类创建的信息。\n", "\n", @@ -740,7 +740,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 特性和描述符是如何相关的 \n", + "## 4.5 特性和描述符是如何相关的 \n", "可以使用如下的一个描述符类来模拟 property 内置函数:" ] }, @@ -820,7 +820,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# `__getattr__` 和 `__getattribute__` \n", + "# 5. `__getattr__` 和 `__getattribute__` \n", "`__getattr__` 和 `__getattribute__` 操作符重载方法提供了拦截类实例的属性获取的另一种方法。 \n", "\n", "属性获取拦截表现为两种形式,可用两个不同的方法来编写:\n", @@ -838,7 +838,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 基础知识 \n", + "## 5.1 基础知识 \n", "如果一个类定义了或继承了如下方法,那么当一个实例用于后面的注释所提到的情况时,它们将自动运行:" ] }, @@ -994,7 +994,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 第一个示例 " + "## 5.2 第一个示例 " ] }, { @@ -1092,7 +1092,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 计算属性 " + "## 5.3 计算属性 " ] }, { @@ -1199,7 +1199,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## `__getattr__` 和 `__getattribute__` 比较 \n", + "## 5.4 `__getattr__` 和 `__getattribute__` 比较 \n", "attr1 是一个类属性,attr2 是一个实例属性,attr3 是一个虚拟的管理属性,当获取时计算它:" ] }, @@ -1284,14 +1284,14 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 管理技术比较 " + "## 5.5 管理技术比较 " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## 拦截内置操作属性 \n", + "## 5.6 拦截内置操作属性 \n", "对于隐式地使用内置操作获取的方法名属性,这些方法可能根本不会运行。这意味着操作符重载方法调用不能委托给被包装的对象,除非包装类自己重新定义这些方法。 \n", "\n", "换句话说,在 Python 3 的类中,没有直接的方法来通用地拦截像打印和加法这样的内置操作。 \n", @@ -1411,8 +1411,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 示例:属性验证 \n", - "## 使用特性来验证 \n", + "# 6. 示例:属性验证 \n", + "## 6.1 使用特性来验证 \n", "特性根据属性访问自动运行代码,但是关注属性的一个特定集合,它们不会用来广泛地拦截所有属性。 \n", "\n", "`__init__` 构造函数方法内部的属性赋值也触发了特性的 setter 方法。 \n", @@ -1523,7 +1523,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 使用描述符验证 \n", + "## 6.2 使用描述符验证 \n", "特性基本上是描述符的一种受限制的形式。和特性不同,描述符有自己的状态,并且它们是一种更为通用的方案。 \n", "\n", "实际的 name 值附加到了描述符对象,而不是客户类实例。 " @@ -1586,7 +1586,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 使用 `__getattr__` 来验证 \n", + "## 6.3 使用 `__getattr__` 来验证 \n", "像 `__getattr__` 这样的通用工具可能更适合于通用委托,而特性和描述符更直接是为了管理特定属性而设计。" ] }, @@ -1634,7 +1634,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 使用 `__getattribute__` 验证 \n", + "## 6.4 使用 `__getattribute__` 验证 \n", "由于每个属性获取都指向了 `__getattribute__`,所以这里我们不需要压缩名称以拦截它们(acct 存储为 acct)。 \n", "\n", "对于设置和获取未管理的属性(例如, addr ),这个版本都会引发额外调用。如果速度极为重要,这个替代方法可能会是所有方案中最慢的。" @@ -1704,7 +1704,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.5" + "version": "3.6.8" } }, "nbformat": 4, diff --git "a/Learning Python/8343円200円201円351円253円230円347円272円247円350円257円235円351円242円230円/3. 350円243円205円351円245円260円345円231円250円.ipynb" "b/Learning Python/8343円200円201円351円253円230円347円272円247円350円257円235円351円242円230円/3. 350円243円205円351円245円260円345円231円250円.ipynb" index aaddec0..04cbe1e 100644 --- "a/Learning Python/8343円200円201円351円253円230円347円272円247円350円257円235円351円242円230円/3. 350円243円205円351円245円260円345円231円250円.ipynb" +++ "b/Learning Python/8343円200円201円351円253円230円347円272円247円350円257円235円351円242円230円/3. 350円243円205円351円245円260円345円231円250円.ipynb" @@ -4,19 +4,19 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 什么是装饰器 \n", + "# 1. 什么是装饰器 \n", "装饰是为函数和类指定管理代码的一种方式。装饰器本身的形式是处理其他的可调用对象的可调用的对象(如函数)。Python装饰器以两种相关的形式呈现: \n", "- **函数装饰器**:在函数定义的时候进行名称重绑定,提供一个逻辑层来管理函数和方法或随后对它们的调用。\n", "- **类装饰器**:在类定义的时候进行名称重绑定,提供一个逻辑层来管理类,或管理随后调用它们所创建的示例。\n", "\n", "简而言之,装饰器提供了一种方法,在函数和类定义语句的末尾插入自动运行代码——对于函数装饰器,在 def 的末尾;对于类装饰器,在 class 的末尾。 \n", "\n", - "## 管理调用和实例 \n", + "## 1.1 管理调用和实例 \n", "它通过针对随后的调用安装**包装器对象**来实现这一点:\n", "- 函数装饰器安装包装器对象,以在需要的时候拦截随后的**函数调用**并处理它们。\n", "- 类装饰器安装包装器对象,以在需要的时候拦截随后的**实例创建调用**并处理它们。\n", "\n", - "## 管理函数和类 \n", + "## 1.2 管理函数和类 \n", "- **函数装饰器**也可以用来管理函数对象,而不是随后对它们的调用——例如,把一个函数注册到一个API。\n", "- **类装饰器**也可以用来直接管理类对象,而不是实例创建调用——例如,用新的方法扩展类。" ] @@ -25,8 +25,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 基础知识 \n", - "## 函数装饰器 \n", + "# 2. 基础知识 \n", + "## 2.1 函数装饰器 \n", "函数装饰器主要只是一种语法糖:通过在一个函数的 def 语句的末尾来运行另一个函数,把最初的函数名重新绑定到结果。 \n", "\n", "**用法** \n", @@ -275,7 +275,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 类装饰器 \n", + "## 2.2 类装饰器 \n", "**用法** \n", "在语法上,装饰器是返回一个可调用对象的一个单参数的函数,类装饰器语法:" ] @@ -409,7 +409,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 装饰器嵌套 \n", + "## 2.3 装饰器嵌套 \n", "为了支持多步骤的扩展,装饰器语法允许我们向一个装饰的函数或方法添加包装器逻辑的多个层。当使用这一功能的时候,每个装饰器必须出现在自己的一行中。这种形式的装饰器语法:" ] }, @@ -448,7 +448,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 装饰器参数 \n", + "## 2.4 装饰器参数 \n", "函数装饰器和类装饰器似乎都能接受参数,尽管实际上这些参数传递给了真正返回装饰器的一个可调用对象,而装饰器反过来又返回一个可调用对象。例如,如下代码:" ] }, @@ -498,8 +498,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 编写函数装饰器 \n", - "## 跟踪调用 \n", + "# 3. 编写函数装饰器 \n", + "## 3.1 跟踪调用 \n", "如下代码定义并应用一个函数装饰器,来统计对装饰的函数的调用次数,并且针对每一次调用打印跟踪信息:" ] }, @@ -612,7 +612,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 状态信息保持选项 \n", + "## 3.2 状态信息保持选项 \n", "有多种方法来实现状态保持:实例属性、全局变量、非局部变量和函数属性。 \n", "\n", "**类实例属性** \n", @@ -710,7 +710,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 类错误之一:装饰类方法 \n", + "## 3.3 类错误之一:装饰类方法 \n", "第一个版本的 tracer 装饰器对类方法的装饰失效了:" ] }, @@ -950,7 +950,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 计时调用 \n", + "## 3.4 计时调用 \n", "下一个装饰器将对一个装饰的函数的调用进行计时——既有针对一次调用的时间,也有所有调用的总的时间。该装饰器应用于两个函数,以便比较列表解析和 map 内置调用所需的时间:" ] }, @@ -1025,7 +1025,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 添加装饰器参数 \n", + "## 3.5 添加装饰器参数 \n", "前面小节介绍的计时器装饰器有效,但是如果它更加可配置的话,那会更好——例如,提供一个输出标签并且可以打开或关闭跟踪消息,这些在一个通用目的的工具中可能很有用。装饰器参数在这里派上了用场:对它们适当编码后,我们可以使用它们来指定配置选项,这些选项可以根据每个装饰的函数而编码。可以像下面这样添加标签:" ] }, @@ -1151,8 +1151,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 编写类装饰器 \n", - "## 单体类 \n", + "# 4. 编写类装饰器 \n", + "## 4.1 单体类 \n", "由于类装饰器可以拦截实例创建调用,所以它们可以用来管理一个类的所有实例,或者扩展这些实例的接口。以下代码实现了传统的单体编码模式,其中最多只有一个类的一个实例存在。其单体函数为管理的属性定义并返回一个函数,并且 @ 语法自动在这个函数中包装了一个主体类:" ] }, @@ -1266,7 +1266,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 跟踪对象接口 \n", + "## 4.2 跟踪对象接口 \n", "类装饰器基本上可以在实例上安装一个包装器逻辑层,来以某种方式管理对其接口的访问。 \n", "\n", "当获取未定义的属性名的时候, `__getattr__` 会运行;我们可以使用这个钩子来拦截一个控制器类中的方法调用,并将它们传递给一个嵌入的对象。 \n", @@ -1403,7 +1403,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 为什么使用装饰器 \n", + "## 4.3 为什么使用装饰器 \n", "为什么我们只是展示不使用装饰器的方法来实现单体呢?从负面的角度讲,**类装饰器**有两个潜在的缺陷:\n", "- 类型修改\n", " - 当插入包装器的时候,一个装饰器函数或类不会保持其最初的类型——其名称重新绑定到一个包装器对象,在使用对象名称或测试对象类型的程序中,这可能会很重要。在单体的例子中,装饰器和管理函数的方法都为实例保持了最初的类类型;在跟踪器的代码中,没有一种方法这么做,因为需要有包装器。\n", @@ -1423,7 +1423,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 直接管理函数和类 \n", + "## 4.4 直接管理函数和类 \n", "假设你需要被另一个应用程序使用的方法或类注册到一个API,以便随后处理(可能该API随后将会调用该对象,以响应事件)。这一思路如下的简单实现定义了一个装饰器,它既应用于函数也应用于类,把对象添加到一个基于字典的注册中。由于它返回对象本身而不是一个包装器,所以它没有拦截随后的调用:" ] }, @@ -1578,7 +1578,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.5" + "version": "3.6.8" } }, "nbformat": 4, diff --git "a/Learning Python/8343円200円201円351円253円230円347円272円247円350円257円235円351円242円230円/4. 345円205円203円347円261円273円.ipynb" "b/Learning Python/8343円200円201円351円253円230円347円272円247円350円257円235円351円242円230円/4. 345円205円203円347円261円273円.ipynb" index 6e7565b..3b02627 100644 --- "a/Learning Python/8343円200円201円351円253円230円347円272円247円350円257円235円351円242円230円/4. 345円205円203円347円261円273円.ipynb" +++ "b/Learning Python/8343円200円201円351円253円230円347円272円247円350円257円235円351円242円230円/4. 345円205円203円347円261円273円.ipynb" @@ -4,13 +4,13 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 要么是元类,要么不是元类 \n", + "# 1. 要么是元类,要么不是元类 \n", "元类主要是针对那些构建API和工具供他人使用的程序员。 \n", "\n", - "## 提高魔力层次 \n", + "## 1.1 提高魔力层次 \n", "元类允许我们在一条 class 语句的末尾,插入当创建一个类对象的时候自动运行的逻辑。这个逻辑不会把类名重新绑定到一个装饰器可调用对象,而是把类自身的创建指向特定的逻辑。 \n", "\n", - "## "辅助"函数的缺点 \n", + "## 1.2 "辅助"函数的缺点 \n", "元类常常是可选的,我们通常可以通过管理器函数(有时候叫做"辅助"函数)传递类对象来实现同样的效果,这和我们通过管理器代码传递函数和实例来实现装饰器的目的很相似。 \n", "\n", "然而,元类:\n", @@ -23,8 +23,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 元类模型 \n", - "## 类是 type 的实例 \n", + "# 2. 元类模型 \n", + "## 2.1 类是 type 的实例 \n", "在 Python 3 中,用户定义的类对象是名为 type 的对象的实例, type 本身是一个类。 \n", "\n", "type 内置函数返回任何对象的类型(它本身是一个对象)。对于列表这样的内置类型,实例的类型是一个内置的列表类型,但是,列表类型的类型是类型 type 自身——顶层的 type 对象创建了具体的类型,具体的类型创建了实例。 " @@ -167,14 +167,14 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 元类是 Type 的子类 \n", + "## 2.2 元类是 Type 的子类 \n", "由于类实际上是 type 类的实例,从 type 的定制的子类创建类允许我们实现各种定制的类。\n", "- type 是产生用户定义的类的一个类。\n", "- 元类是 type 类的一个子类。\n", "- 类对象是 type 类的一个实例,或一个子类。\n", "- 实例对象产生自一个类。 \n", "\n", - "## Class 语句协议 \n", + "## 2.3 Class 语句协议 \n", "当 Python 遇到一条 class 语句,它会运行其嵌套的代码块以创建其属性——所有在嵌套代码块的顶层分配的名称都生成类对象中的属性。这些名称通常是嵌套的 def 所创建的方法函数,但是,它们也可以是分配来创建由所有实例共享的类数据的任意属性。 \n", "\n", "Python 遵从一个标准的协议来使这发生:在**一条class语句的末尾**,并且在运行了一个命名空间词典中的所有嵌套代码之后,它调用 type 对象来创建 class 对象:" @@ -353,7 +353,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 声明元类 \n", + "# 3. 声明元类 \n", "在类标题中把想要的元类作为一个关键字参数列出来:" ] }, @@ -419,8 +419,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 编写元类 \n", - "## 基本元类 \n", + "# 4. 编写元类 \n", + "## 4.1 基本元类 \n", "最简单元类只是带有一个 `__new__` 方法的 type 的子类,该方法通过运行 type 中的默认版本来创建类对象。" ] }, @@ -488,7 +488,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 定制构建和初始化 \n", + "## 4.2 定制构建和初始化 \n", "元类也可以接入 `__init__` 协议,由 type 对象的 `__call__` 调用:通常,`__new__` 创建并返回类对象,`__init__` 初始化已经创建的类。" ] }, @@ -551,7 +551,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 其他元类编程技巧 \n", + "## 4.3 其他元类编程技巧 \n", "\n", "**使用简单的工厂函数** \n", "\n", @@ -761,7 +761,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 继承与实例的关系 \n", + "# 5. 继承与实例的关系 \n", "- **元类继承自 type 类。** 元类通常重新定义 type 类的 `__new__` 和 `__init__`,以定制类创建和初始化,但是,如果它们希望直接捕获类末尾的创建调用的话,它们也可以重新定义 `__call__`。\n", "- **元类声明由子类继承。** metaclass=M 声明由该类的子类继承,因此,对于在超类链中继承了这一声明的每个类的构建,该元类都将运行。\n", "- **元类属性没有由类实例继承。**由于类是元类的实例,所以元类中定义的行为应用于类,而不是类随后的实例。实例从它们的类和超类获取行为,但是,不是从任何元类获取行为。\n", @@ -1031,7 +1031,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 元类 VS 超类 \n", + "## 5.1 元类 VS 超类 \n", "A 元类的实例 B 可以获取 A 的属性,但是 B 自己的实例不能继承该属性。" ] }, @@ -1182,7 +1182,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 元类方法 \n", + "# 6. 元类方法 \n", "元类中的方法处理他们的实例 —— 类,不使用常规实例对象的 \"self\",而是类自身。" ] }, @@ -1331,7 +1331,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 元类方法 VS 类方法 \n", + "## 6.1 元类方法 VS 类方法 \n", "虽然它们在继承可见性上有所不同,很像类方法,但是元类方法是用来管理类级数据的。元类方法只能通过类访问,并且不需要显式的 classmethod 类级数据声明来绑定类。换句话说,元类方法可以被认为是隐式类方法:" ] }, @@ -1432,7 +1432,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 元类方法中的操作符重载 \n", + "## 6.2 元类方法中的操作符重载 \n", "元类也可以使用操作符重载来使内置操作适用于它们的实例类。" ] }, @@ -1529,8 +1529,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 示例:向类添加方法 \n", - "## 手动扩展 " + "# 7. 示例:向类添加方法 \n", + "## 7.1 手动扩展 " ] }, { @@ -1595,7 +1595,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 基于元类的扩展 \n", + "## 7.2 基于元类的扩展 \n", "通过这种方式,我们避免了对任何给定的类修改扩展的机会。此外,在单独位置编写扩展更好地支持了未来的修改——集合中的所有类都将自动接收修改。" ] }, @@ -1652,7 +1652,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 元类 VS 类装饰器:第二回合 \n", + "## 7.3 元类 VS 类装饰器:第二回合 \n", "类装饰器常常和元类在功能上有重合。\n", "- 在新类创建后,在 class 语句的末尾,类装饰器把类名重新绑定到一个函数的结果。\n", "- 元类通过在一条 class 语句的末尾把类对象创建过程路由到一个对象来工作。\n", @@ -1823,8 +1823,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 示例:对方法应用装饰器 \n", - "## 用装饰器手动跟踪" + "# 8. 示例:对方法应用装饰器 \n", + "## 8.1 用装饰器手动跟踪" ] }, { @@ -1907,7 +1907,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 用元类和装饰器跟踪 " + "## 8.2 用元类和装饰器跟踪 " ] }, { @@ -1963,7 +1963,7 @@ "source": [ "在类创建的时候,元类自动把函数装饰器应用于每个方法,并且函数装饰器自动拦截方法调用,以便在此输出中打印出跟踪消息。 \n", "\n", - "## 把任何装饰器应用于方法 " + "## 8.3 把任何装饰器应用于方法 " ] }, { @@ -2037,7 +2037,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 元类 VS 类装饰器:第三回合\n", + "## 8.4 元类 VS 类装饰器:第三回合\n", "它定义并使用一个**类装饰器**,该装饰器把一个**函数装饰器**应用于一个类的所有方法。" ] }, @@ -2105,7 +2105,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.5" + "version": "3.6.8" } }, "nbformat": 4, From 00dce99c7e7936bd5b0731adc501a830e4d3eba7 Mon Sep 17 00:00:00 2001 From: GitLanx <675579465@qq.com> Date: 2020年9月21日 15:17:04 +0800 Subject: [PATCH 7/7] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20=E6=95=B0=E5=AD=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2. 346円225円260円345円255円227円.ipynb" | 48 +++++++++++++++++-- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git "a/Learning Python/2343円200円201円347円261円273円345円236円213円345円222円214円350円277円220円347円256円227円/2. 346円225円260円345円255円227円.ipynb" "b/Learning Python/2343円200円201円347円261円273円345円236円213円345円222円214円350円277円220円347円256円227円/2. 346円225円260円345円255円227円.ipynb" index 5332f03..441ca18 100644 --- "a/Learning Python/2343円200円201円347円261円273円345円236円213円345円222円214円350円277円220円347円256円227円/2. 346円225円260円345円255円227円.ipynb" +++ "b/Learning Python/2343円200円201円347円261円273円345円236円213円345円222円214円350円277円220円347円256円227円/2. 346円225円260円345円255円227円.ipynb" @@ -274,7 +274,7 @@ "**X / Y** \n", "真除法,无论任何类型都会保持小数部分。 \n", "**X // Y** \n", - "Floor 除法,不考虑操作对象的类型,总会省略掉结果的小数部分。 " + "Floor 除法,不考虑操作对象的类型,运算结果总是向负无穷的方向舍入。 " ] }, { @@ -428,6 +428,46 @@ "(2 + 1j) * 3" ] }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(1+2j)" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "complex('1+2j') # 将字符串或数字转换成复数,字符串 + - 周围不能有空格" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(1+0j)" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "complex(1)" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -994,7 +1034,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "使用小数对象,结果能够改正(接受参数为字符串)" + "使用小数对象,结果能够改正,参数可以是整数,字符串,元组,float,或另一个 Decimal 对象。" ] }, { @@ -1309,7 +1349,7 @@ "## 3.3 集合(Set)\n", "集合是一些唯一的、不可变的对象的一个无序集合,这些对象支持与数学集合理论相对应的操作。 \n", "\n", - "要创建一个集合对象,需要向内置的set函数传递一个序列或其他的可迭代的对象。" + "要创建一个集合对象,需要向内置的 set 函数传递一个序列或其他的可迭代的对象。" ] }, { @@ -1826,7 +1866,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.5" + "version": "3.7.3" } }, "nbformat": 4,

AltStyle によって変換されたページ (->オリジナル) /