python3.x随手笔记2

对象,价值观和类型 

对象 Python的抽象的数据。 所有的数据在一个Python程序 表示对象或对象之间的关系。 (在某种意义上,在 符合冯诺依曼模型的代码也“存储程序计算机” 由对象。)

每一个对象都有一个身份,一个类型和一个值。 一个对象的 身份 从来没有 改变一旦被创建,你可能认为这是对象的地址 内存。 “ 是 “运营商比较两个对象的身份, id() 函数返回一个整数代表其身份(目前 实现为其地址)。 一个对象的 类型 也是不变的。 [1] 一个对象的类型决定了操作对象支持(如。 :“ 它有长度吗?”),也定义了对象的可能值 类型。 的 类型() 函数返回一个对象的类型(这是一个对象 本身)。 的 价值 可以改变的对象。 对象,其价值可以 据说是改变 可变的 ,对象的值是不变的,一旦他们 创建了被称为 不可变的 。 (不可变容器对象的价值 包含对一个可变对象的引用可以改变时,后者的价值 改变;然而容器仍然被认为是不可变的,因为 它包含的对象集合不能改变。 所以,不变性 严格一样有一个不变的值,它是更微妙的)。 一个 对象的可变性是由其类型,例如,数字、字符串 和元组是不可变的,而词典和列表是可变的。

对象是从来没有明确地摧毁了;然而,当他们成为遥不可及的 他们可能被垃圾收集。 一个实现允许推迟垃圾 收集或者干脆省略它——它是一种实现质量 垃圾收集是如何实现的,只要没有对象收集 仍可及。

CPython的实现细节: CPython的目前使用引用计数和(可选)推迟了计划 相关的周期性检测垃圾,收集就大多数对象 当他们成为遥不可及的,但不能保证收集垃圾 包含循环引用。 看到的文档 gc 模块控制循环垃圾的收集信息。 其他实现不同和CPython的可能变化。 不依赖于立即终结的对象,当他们成为 遥不可及的(例:总是关闭文件)。

注意,使用实现的跟踪或调试设备 保持对象通常是收藏价值。 还要注意,抓住 一个异常与“ 试一试 … 除了 声明可能保持 对象还活着。

一些对象包含引用“外部”资源,比如文件或打开 窗户。 据悉,这些资源是当对象被释放 垃圾收集,但由于垃圾收集是没有保证的, 这样的对象也提供了一个显式释放外部资源的方式, 通常是一个 close() 方法。 项目是明确强烈推荐 这样的对象。 “ 试一试 … 最后 的声明 和“ 与 ”声明中提供便捷的方法。

一些对象包含对其他对象的引用,这些被称为 容器 。 容器的例子有元组、列表和字典。 的引用 集装箱的价值的一部分。 在大多数情况下,当我们谈论的价值 容器,我们暗示的值,而不是包含的对象的身份; 然而,当我们谈论一个容器的可变性,只有身份 立即包含的对象是隐含的。 所以,如果一个不可变的容器 (如一个元组)包含一个引用一个可变对象,如果它的值变化 可变的对象改变了。

对象的类型影响几乎所有方面的行为。 甚至的重要性 对象身份在某种程度上影响:对于不可变类型,操作 计算新值可能会返回一个引用任何现有的对象 可变对象相同的类型和值,而这是不允许的。 例如, 后 一个 1; 一个和 可能会或可能不会引用同一个对象 值,根据具体的实现方式,但之后 []; [] 和 保证指的是两个不同的,独特的,新吗 创建空的列表。 (注意, [] 分配相同的对象 和 )。

标准的类型层次结构 

下面是一个列表的Python内置类型。 扩展模块 (写在C、Java或其他语言,根据实现) 定义额外的类型。 Python的未来版本可能添加类型的类型 层次结构(如。 整数、有理数高效存储阵列,等等), 尽管这样的增加将会提供通过标准库。

下面的一些类型描述包含一段特殊清单” 属性。 “这些属性实现和提供 不是用于一般用途。 它们的定义在未来可能会改变。

没有一个

这种类型只有一个值。 有一个单一对象这个值。 这 对象是通过内置的名字 没有一个 。 它是用来表示 在很多情况下缺乏价值,如 从函数返回 不显式地返回任何东西。 它的真值是错误的。

NotImplemented

这种类型只有一个值。 有一个单一对象这个值。 这 对象是通过内置的名字 NotImplemented 。 数值方法 和丰富的比较方法可以返回这个值如果不实现 操作的操作数。 (翻译会试试的 反映操作,根据运营商或其他后备)。 它的 真值是正确的。

省略

这种类型只有一个值。 有一个单一对象这个值。 这 通过文字对象访问 … 或内置的名称 省略 。 它的真值是正确的。

numbers.Number

这些都是由数字文本并返回结果的算术 运算符和算术内置函数。 数字对象是不可变的; 一旦创建它们的价值永远不会改变。 Python数字当然是强烈 与数学相关的数字,但数值的局限性 在电脑。

Python区分整数、浮点数和复杂 数字:

numbers.Integral

这些代表元素从数学组整数(积极和 负面的)。

有两种类型的整数:

整数( int )

这些代表的数字在一个无限的范围内,可用(虚拟) 只有记忆。 为目的的转变和掩码操作,一个二进制 表示假设,负数表示的一个变体 2的补码赋予无限的幻想串标志位 扩展到左边。
布尔值( bool )

这些代表了真值虚假和真实的。 两个对象代表 假和真值是唯一的逻辑对象。 是一个布尔类型 整数类型的子类型,布尔值像0和1的值, 分别在几乎所有情况下,当转换为例外 一个字符串,字符串 “假” 或 “真正的” 分别返回。

整数表示的规则是为了给最有意义的 解释涉及负整数的转变和掩模操作。

numbers.Real 浮动 )

这些代表机器双精度浮点数。 你是 的摆布底层机器体系结构(C或Java 实现)的接受范围和处理溢出。 Python不 支持单精度浮点数;在处理器和储蓄 内存使用,通常使用这些的原因是相形见绌 在Python中使用对象的开销,所以没有理由的复杂化 语言有两种浮点数。

numbers.Complex 复杂的 )

这些代表复数一双机器双精度 浮点数。 应用相同的警告浮点数。 一个复数的实部和虚部 可以通过检索 只读属性 z.real 和 z.imag 

序列

这些代表有限点集被非负数字。 的 内置函数 len() 返回条目的数量的一个序列。 当 一个序列的长度 ,该指数集包含数字0,1, …, 1。 项 我 的序列 一个 被选中的 (我) 

还支持序列切片: (i,j) 选择所有项目与索引 这样的 那 我 < = 。 作为一个表达式时,一片 相同类型的序列。 这意味着指数集重新编号 它从0开始。

一些序列也支持“扩展切片”,第三个“步骤”参数: (我:j k): 选择所有项目的 一个 与指数 在哪里 我 n * k > = 和 我 < = 

序列是杰出的根据他们的可变性:

不变的序列

一个不可变的序列类型的一个对象不能改变一旦创建。 (如果 对象包含对其他对象的引用,这些其他对象 可变的,可能改变;然而,直接的对象集合 引用一个不可变对象不能改变。)

以下类型是不可变的序列:

字符串

字符串对象的项目是Unicode代码单元。 Unicode代码 单位由字符串对象表示一个条目,可以容纳 一个16位或32位的值代表一个Unicode序数(最大 值的顺序给出 sys.maxunicode ,取决于 Python是如何配置在编译时)。 代理人对可能 在Unicode对象,将作为两个单独的报告 物品。 内置的功能 科() 和 奥德() 转换 表示Unicode代码单元之间和非负整数 Unicode标准3.0中定义的顺序。 从和转换 其他编码可以通过字符串的方法 编码()

元组

一个元组的物品任意Python对象。 元组的两个或两个 更多的项目是由逗号分隔的表达式列表。 一个元组 一个条目(singleton)可以由粘贴一个逗号 表达式(表达式本身并不创建一个元组, 必须使用括号表达式分组)。 一个空 元组可以由一个空对括号中。

字节

一个字节对象数组。 物品是8位字节, 由整数范围0 < = x < 256。 字节字符 (如 b 'abc ' 和内置函数 字节() 可用于 构造字节对象。 同时,字节对象可以解码字符串 通过 decode() 方法。

可变序列

可变序列可以改变后创建的。 订阅和 切片符号可以作为分配和追求的目标 ▽ (删除)语句。

目前有两种内在可变序列类型:

列表

是任意的Python对象列表的项目。 列表是由 把一个以逗号分隔的在方括号表达式。 (注意 没有特殊情况需要表单列表长度为0或1的。)

字节数组

是一个可变数组中bytearray对象。 他们是由内置的 中bytearray() 构造函数。 除了可变(因此 unhashable),否则字节数组提供相同的接口和 功能不变的字节对象。

扩展模块 数组 提供了一个额外的例子 可变序列类型,一样 集合 模块。

集类型

这些代表无序,有限集的独一无二的,不可变对象。 因此, 他们不能被任何下标索引。 然而,他们可以遍历, 内置的函数 len() 返回一组项的项数。常见 用途集快速加入测试,删除重复的序列, 和计算数学运算,如十字路口,联盟的区别, 和对称差分。

组元素,同样的不变性规则应用字典键。 请注意 数值类型为数值比较遵守正常的规则:如果两个数字 比较相同(例如, 和 1.0 ),可以包含在一个只有一个人 集。

目前有两个内在的类型:

这些代表一组可变的。它们是由内置的 设置() 构造函数可以通过几种方法修改之后,等 add() 

冰冻的集

这些代表一套不变的。它们是由内置的 frozenset() 构造函数。 作为一个frozenset是不可变的 hashable 再次,它可以使用另一个集合的一个元素,或作为 一个字典键。

映射

这些代表有限集的对象被任意指数集。 的 下标符号 一个[k] 选择项索引 从映射 一个 ,这可用于表情和作业的目标或 ▽ 语句。 内置的函数 len() 返回的数量 项的映射。

目前一个内在映射类型:

字典

这些代表有限集的对象索引近任意值。 的 只有类型的值包含列表或不能接受的作为键值 字典或其他可变类型相比,而不是价值 对象的身份,是有效实施的原因 字典需要一个关键的散列值保持不变。 数值类型使用 为数字键遵守正常的规则比较:如果两个数字比较 平等的(例如, 和 1.0 ),那么他们可以交替使用索引 相同的词条。

字典是可变的,他们可以创造的 {…} 符号(见 部分 字典显示 )。

扩展模块 dbm.ndbm 和 dbm.gnu 提供 额外的映射类型的例子,一样 集合 模块。

可调用的类型

这些类型的函数调用操作(参见 调用 )可以应用:

用户定义函数

由一个函数创建一个用户定义函数对象(见定义 部分 函数定义 )。 它应该被称为一个参数列表 包含相同数量的物品作为函数的形式参数 列表。

特殊属性:

属性意义 
__doc__ 函数的文档 字符串,或 没有一个 如果 不可用 可写的
__name__ 函数的名字 可写的
__module__ 模块的名称 函数中定义,或 没有一个 如果不可用。 可写的
__defaults__ tuple包含违约 这些参数值 默认参数, 或 没有一个 如果没有参数 有一个默认值 可写的
__code__ 代码对象代表 编译后的函数体。 可写的
__globals__ 的引用字典 包含函数的 全局变量, 全局名称空间的 模块的功能 被定义。 只读
__dict__ 名称空间支持 任意函数 属性。 可写的
__closure__ 没有一个 或者一个元组的细胞 包含绑定的 函数的自由变量。 只读
__annotations__ 包含注释的dict 的参数。 的钥匙 关键字参数 的名字,或者 “返回” 为 返回注释,如果 提供。 可写的
__kwdefaults__ 一个包含违约dict keyword-only参数。 可写的

大部分的属性标签“可写”检查分配的值的类型。

函数对象也支持获取和设置任意属性 可以被使用,例如,附加元数据功能。 常规属性 通过用于获取和设置这些属性。 请注意,当前 在用户自定义函数实现只支持函数属性。 功能属性内置函数可能在未来支持。

额外的信息可以从其检索函数的定义 代码对象;参见下面描述的内部类型。

实例方法

一个类对象方法结合实例,和任何一个类实例 可调用对象(通常一个用户定义的函数)。

特殊的只读属性: __self__ 是类的实例对象, __func__ 函数对象; __doc__ 是方法的 文档(一样 __func__.__doc__ ); __name__ 是 方法名(一样 __func__.__name__ ); __module__ 是 模块中定义的方法的名称,或 没有一个 如果不可用。

方法还支持访问任意函数(但不是设置) 底层函数对象属性。

时可以创建用户定义的方法对象的一个属性 类(也许通过该类的一个实例),如果该属性是一个 用户定义函数对象或类方法对象。

当创建一个实例方法对象检索一个用户定义的 通过一个函数对象从一个类的实例,它 __self__ 属性是实例和方法对象 绑定。 新方法的 __func__ 属性是原始的 函数对象。

当创建一个用户定义的方法对象检索另一种方法 从一个类或对象实例的行为是一样的 函数对象,除了 __func__ 属性的新 但它不是原来的方法对象实例 __func__ 属性。

当一个类创建对象的方法检索实例方法 从一个类或对象实例,它的 __self__ 属性是 类本身,它的 __func__ 属性的函数对象 底层的类方法。

当一个对象实例方法被调用时,底层的函数 ( __func__ ),插入类实例 ( __self__ 在参数列表的前面。 例如,当 是一个类包含一个定义一个函数 f() 是一个实例 ,称 范(1) 是 相当于调用 出口(x, 1) 

当一个对象实例方法来源于一个类方法对象, 存储在类实例 __self__ 会类 本身,以便调用 范(1) 或 由(1) 相当于 调用 f(C,1) 在哪里 是底层的函数。

注意,转换函数对象的实例方法 对象发生每次属性从实例中检索。 在 某些情况下,一个卓有成效的优化分配属性到本地 变量,称之为局部变量。 还要注意,这个 转换为用户定义函数只发生;其他可调用的 检索对象(和不可赎回所有对象) 转换。 同样重要的是要注意,用户自定义函数 类的属性的实例转换为绑定吗 方法,这 只有 当这个函数的一个属性 类。

发生器功能

使用的函数或方法 收益率 语句(参见 收益率的声明 )被称为 生成器函数 。 这样一个函数,当 调用时,总是返回一个迭代器对象可以用来执行 身体的功能:调用迭代器 __next__() 方法将 导致该函数执行,直到它提供了一个使用价值 收益率 声明。 当执行一个函数 返回 语句或脱落, 抛出StopIteration 异常和迭代器将已达到的集合 返回值。

内置函数

一个内置的函数对象是一个C函数的包装器。 的例子 内置函数 len() 和 sin() 数学 是一个 标准的内置模块)。 的数量和类型的参数 由C函数决定。 特殊的只读属性: __doc__ 是函数的文档字符串,还是 没有一个 如果 不可用; __name__ 函数的名称; __self__ 是 设置为 没有一个 (但见下一项); __module__ 的名字是 该模块中定义的函数 没有一个 如果不可用。

内置的方法

这确实是一个不同的伪装的内置函数,包含 一个对象传递给C函数作为隐式额外的参数。 的一个例子 一个内置的方法 alist.append() ,假设 船向一边倾斜的 是一个列表对象。 在 这种情况下,特殊的只读属性 __self__ 设置为对象 用 船向一边倾斜的 

类是可调用的。 通常这些对象作为新工厂 自己的实例,但变化是可能的类类型 覆盖 __new__() 。 调用的参数传递 __new__() 在典型的情况下, __init__() 来 初始化新实例。
类实例
任意类的实例可以定义一个可调用的 __call__() 类的方法。
模块

模块是进口的 进口 语句(参见 import语句 )。 有一个模块对象 名称空间实现dictionary对象(这是字典引用 __globals__属性的函数在模块中定义)。 属性 引用翻译在这本字典查找,例如, m.x 是 相当于 m.__dict__[x] 。 一个模块对象不包含代码 对象用于初始化模块(因为它不需要一旦 初始化完成)。

属性赋值更新模块的名称空间字典,例如, m.x 相当于 m.__dict__[x] 

特殊的只读属性: __dict__ 模块的名称空间是吗 字典对象。

CPython的实现细节: 因为字典CPython的清理模块,模块 字典将被清除时,模块即使超出范围 词典还住引用。 为了避免这种情况,复制字典 或保持周围的模块,而直接使用它的字典。

预定义的属性(可写): __name__ 模块的名字; __doc__ 是模块的文档字符串,还是 没有一个 如果 不可用; __file__ 文件的路径名来自哪个模块 是加载,如果从文件加载。 的 __file__ 属性不是 礼物给C模块静态链接到解释器; 扩展模块从一个共享库,动态加载路径名 共享库文件。

定制类

自定义类类型通常是由类定义(见部分 类定义 )。 一个由一个字典对象实现类都有一个名称空间。 类属性引用翻译在这本字典查找,例如, C.x 是翻译 C.__dict__[x] (尽管有很多 钩子允许的其他方式定位属性)。 当属性 没有找到名字,搜索仍在基类的属性。 这个搜索的基类使用的C3方法解析顺序 正确的行为即使在“钻石”继承结构的存在 哪里有多重继承路径回到共同的祖先。

当一个类属性(类的引用 ),将产生一个 类方法对象,它转换成一个对象的实例方法 __self__ 属性 。 当它将产生一个静态的 方法对象,它转换成对象封装静态方法 对象。 参见 实现描述符 另一个属性的方式 从一个类检索可能不同于那些实际上包含在它 __dict__ 

类属性赋值更新类的字典,字典 一个基类。

一个类对象可以调用(见上图)来生成一个类实例(见下文)。

特殊属性: __name__ 是类名; __module__ 是 类定义的模块名称; __dict__ 是 字典包含类的命名空间; __bases__ 是一个元组 (可能为空或一个单例)包含基类,顺序 他们的出现在基类列表中; __doc__ 是类的 如果未定义的文档字符串,或没有。

类实例

创建一个类实例调用一个类对象(见上图)。 一个类 实例有一个名称空间实现为一个字典 搜索属性引用。 当一个属性没有找到 ,实例的类有一个属性的名称,搜索 继续与类属性。 如果一个类属性是发现 用户定义的函数对象,它转化为一个实例方法 的对象 __self__ 属性是实例。 静态方法和 类方法对象也改变了,见上图“类”。 看到 部分 实现描述符 为另一个类的属性 通过检索实例可能不同于实际存储在对象 类的 __dict__ 。 如果没有找到类属性, 对象的类都有一个 __getattr__() 方法,叫做满足 查找。

属性分配和删除更新实例的字典,从来没有一个 类的字典。 如果类有一个 __setattr__() 或 __delattr__() 方法,这就是所谓的而不是更新实例 直接的字典。

类实例可以伪装成数字序列,如果他们有或映射 方法与某些特别的名字。 参见 特殊的方法名称 

特殊属性: __dict__ 是属性字典; __class__进行 是类的实例。

I / O对象(也称为文件对象)

一个 文件对象 代表一个打开的文件。 各种快捷键 创建文件对象:可用 open() 内置函数, 也 os.popen() os.fdopen() makefile() 方法 的套接字对象(或者由其他函数或方法 通过扩展模块)。

的对象 sys.stdin sys.stdout 和 sys.stderr 是 初始化文件对象对应翻译的标准 输入、输出和错误流;他们都是在文本模式和开放 所以按照定义的接口 io.TextIOBase 抽象类。

内部类型

内部使用的几个类型翻译暴露给用户。 他们的 定义可能会改变未来版本的翻译,但它们 这里提到的完整性。

代码对象

代码对象表示 byte-compiled 可执行Python代码,或 字节码 。 代码对象和一个函数对象的区别在于功能 对象包含函数的显式引用全局变量(模块 它定义的),而一个代码对象包含没有上下文,也默认吗 参数值是存储在函数对象,而不是在代码中对象 (因为他们代表值计算在运行时)。 不像函数 对象,代码对象是不可变的,不包含(直接或引用 间接)可变的对象。

特殊的只读属性: co_name 给出了函数名; co_argcount 是位置参数的数量(包括参数 和默认值); co_nlocals 使用的局部变量数量吗 的函数(包括参数); co_varnames 是一个元组,它包含 局部变量的名称(从参数名称);co_cellvars 是一个元组,它包含局部变量的名称是什么 引用的嵌套函数; co_freevars 是一个tuple包含吗 自由变量的名字; co_code 是一个字符串序列代表 字节码指令; co_consts 是一个元组,它包含文字吗 使用的字节码;co_names 是一个元组,它包含所使用的名字 字节码; co_filename 是代码的文件名是什么 编译; co_firstlineno 函数的第一行号; co_lnotab 是一个字符串编码映射从字节码补偿 行号(详情见的源代码解释器); co_stacksize 是所需的堆栈大小(包括局部变量); co_flags 是一个整数编码标志的翻译。

定义下列标志位 co_flags :位 0 x04 如果设置 这个函数使用 *参数 语法接受任意数量的 位置参数;一些 如果函数使用的设置 * *关键字 语法接受任意关键字参数; 0 x20 设置 如果函数是一个发电机。

未来的功能声明( 从 __future__ 进口 部门 )也使用位 在 co_flags 表明是否编译了代码对象 特定功能:启用 0 x2000 如果函数编译设置 启用了未来部门;碎片 0 x10 和 0 x1000 在早些时候 版本的Python。

其他位 co_flags 是用于内部使用。

如果一个代码对象表示一个函数,第一项 co_consts 是 文档字符串的函数,或 没有一个 如果未定义。

帧对象

帧对象代表执行框架。 他们可能会发生在回溯对象 (见下文)。

特殊的只读属性: f_back 是前一个堆栈框架 (对来电者),或者 没有一个 如果这是底部堆栈帧; f_code 是对象的代码被执行在这个框架; f_locals 字典是用来查找本地变量; f_globals 用于 全局变量; f_builtins 用于内置(内在)名称; f_lasti 给出了精确的指令(这是一个索引 字节码代码的字符串对象)。

特殊的可写属性: f_trace ,如果不是 没有一个 ,是一个函数 在每个源代码行(这是使用调试器); f_lineno 是当前框架的行号,写这个吗 从内部函数跟踪给定的线(只是最底层的 帧)。 调试器可以实现跳转命令(又名设置下一条语句) 通过编写f_lineno。

回溯对象

回溯对象代表一个堆栈跟踪的一个例外。 回溯对象 是在异常发生时创建的。 当寻找一个异常处理程序 执行堆栈展开,在每个解除回溯对象 前面插入当前的回溯。 当一个异常处理程序 进入,使用堆栈跟踪程序。 (见部分try语句 )。 的第三项是可以访问它的 返回的元组 sys.exc_info() 。 当程序包含不合适 编写处理程序,堆栈跟踪(良好格式化的)标准误差 流;如果解释器是互动的,它还提供给用户 作为 sys.last_traceback 

特殊的只读属性: tb_next 堆栈是下一个水平 跟踪(对发生异常的框架),或 没有一个 如果有 没有下一个层次; tb_frame 指向当前的执行框架 水平; tb_lineno 发生了异常的行号; tb_lasti 表示精确的指令。 行号和最后一个 回溯的指令可能不同于框架对象的行号 如果异常发生在一个 试一试 声明中没有匹配的除外 条款或条款。

片对象

片对象用于表示片 __getitem__() 方法。 他们也由内置的 片() 函数。

特殊的只读属性: 开始 是下界; 停止 是 上限; 一步 是一步价值;每个吗 没有一个 如果省略了。 这些属性可以包含任意类型。

片对象支持一个方法:

片。 指数 自我 长度 
这个方法取一个整数参数 长度 和计算 切片,切片对象描述信息 应用于序列 长度 物品。 它返回一个元组的三个 整数,分别这些 开始 和 停止 指数和 一步 或切片的步幅。 缺失或界外指数 处理的方式与普通片一致。
静态方法对象
静态方法对象提供一种击败的变换函数 上面描述的对象方法对象。 静态方法对象是一个包装器 在任何其他对象,对象通常是一个用户定义的方法。 当一个静态 方法检索对象从一个类或一个类的实例,对象 是包裹返回对象,它不受任何进一步的 转换。 静态方法本身并不是可调用的对象,虽然 他们通常包装对象。 静态方法是由内置的对象 staticmethod() 构造函数。
类方法对象
一个类方法的对象,就像一个静态方法对象,是一个包装 对象,改变的方式,从类和对象检索 类实例。 类方法的行为在这种检索对象 上面所描述的那样,在“用户定义的方法”。 类方法创建对象 内置的 classmethod() 构造函数。

特殊的方法名称 

一个类可以实现某些操作所调用的特殊的语法 (如算术运算或加下标和切片)通过定义方法 有特殊的名字。 这是Python的方法 操作符重载 , 允许类来定义自己的行为语言 操作符。 例如,如果一个类定义了一个方法 __getitem__(), 和 是这个类的一个实例,那么 x[我] 大概是等价的 来 类型(x). __getitem__(x, 我) 。 除了提到的地方,尝试执行一个 操作引发异常时没有适当的方法(通常定义 AttributeError 或 TypeError )。

在实现一个模拟任何内置类型,类是很重要的 模拟实现的程度,它是有意义的 对象建模。 例如,一些序列可能与检索工作 单个元素,但提取一片可能没有意义。 (一个例子 的这是 节点列表 接口在W3C文档对象模型)。

 基本定制 

对象。 __new__ cls … 

创建一个新类的实例 cls 。 __new__() 是一个静态 方法(特殊情况所以你不需要声明它),这个班 其中一个实例请求作为它的第一个参数。 剩下的 参数是传递给对象构造函数表达式(调用 类)。 的返回值 __new__() 应该是新的对象实例吗 (通常的一个实例 cls )。

典型的实现创建一个新类的实例调用 超类的 __new__() 方法使用 超级(currentclass cls). __new__(cls, …) 用适当的参数,然后修改 在必要时创建的实例返回之前。

如果 __new__() 返回一个实例 cls ,然后新实例的 __init__() 方法将被调用 __init__(自我, …) ,在那里 自我 是新实例和剩余的参数是一样的吗 传递给 __new__() 

如果 __new__() 不返回的一个实例吗 cls ,然后新实例的 __init__() 方法将不会被调用。

__new__() 主要目的是允许不可变类型的子类(像什么 int、str或定制实例创建元组)。 这也是常见的 覆盖在自定义元类来创建自定义类。

对象。 __init__ 自我 … 

实例被创建时调用的方法。 参数传递到 类构造函数表达式。 如果基类有一个 __init__() 方法, 派生类的 __init__() 方法,如果有的话,必须显式地调用它 确保适当的初始化基类的实例的一部分; 例子: BaseClass.__init__(自我,(args…)) 。 作为一种特殊的约束 构造函数,不得返回值;这样做会引起 TypeError 在运行时被提出。

对象。 __del__ 自我 

时调用该实例将被摧毁。 这也被称为 析构函数。 如果一个基类 __del__() 方法,派生类的 __del__() 方法,如果有的话,必须显式地调用它,以确保适当的 删除的基类实例的一部分。 请注意,这是可能的 (虽然不推荐!) __del__()方法推迟破坏 创建一个新的实例的引用。 它可能会被称为一个 以后在这个新的引用删除。 它不保证 __del__() 方法被称为对象时仍然存在 解释器退出。

请注意 

 

▽ 并不能直接调用 x.__del__() ——前者衰减 的引用计数 ,而后者只是时调用 引用计数为0。 一些常见的情况 防止一个对象的引用计数为零包括: (如对象间的循环引用。 一个双链接列表,或一棵树 数据结构指针为父母和孩子);一个对象的引用 函数的堆栈帧中,抓到一个例外(回溯 存储在 sys.exc_info()[2] 使堆栈帧活着);或 引用对象的堆栈框架提出了一个未处理的 除了在交互模式下(中存储的回溯 sys.last_traceback 让活着的堆栈帧)。 第一个情况 只能弥补通过显式地打破了周期;后两个吗 的情况下可以通过存储解决 没有一个 在 sys.last_traceback 。 检测到循环引用的垃圾时,选择循环 启用检测器(在默认情况下),但只能清理 没有Python级__del__() 涉及的方法。 指的是 文档 gc 关于模块的更多信息 __del__() 方法是由循环处理探测器,特别是 的描述 垃圾 价值。

警告 

 

由于不稳定的情况下 __del__() 方法是 调用时,忽略它们的执行过程中发生的异常,一个警告 是印刷的 sys.stderr 代替。 另外,当 __del__() 在调用 回应一个模块(如被删除。 当执行程序 ),其他引用的全局变量__del__() 方法可能已经 被删除或被拆除的过程中(如进口 机器关闭)。 由于这个原因, __del__() 方法 应该做的绝对 最低需要保持外部的不变量。 从1.5版本开始, Python保证全局名字始于一个下划线 从他们的模块在其他全局删除删除;如果没有其他的 这样的全局存在的引用,这可能有助于确保进口 模块时仍然可用 __del__() 方法是 调用。

对象。 __repr__ 自我 

叫的 repr() 内置函数来计算“官方”字符串 表示一个对象。 如果可能的话,这应该看起来像 有效的Python表达式,可以用来创建一个对象 相同的值(给定一个适当的环境)。 如果这是不可能的 字符串的形式 <…一些 有用的 描述…> 应该被归还。 返回值必须是一个字符串对象。 如果一个类定义 __repr__() 但不是 __str__() ,然后 __repr__() 也用于当一个吗 “非正式”字符串表示该类的实例是必需的。

这是通常用于调试,所以重要的是表示 信息丰富而清晰。

对象。 __str__ 自我 

叫的 str() 内置函数和的 print() 函数 计算“非正式”对象的字符串表示。 这是不同的 从 __repr__() 它不需要一个有效的Python 表达式:更方便或简洁的表示可以使用。 返回值必须是一个字符串对象。

对象。 __format__ 自我 format_spec 

叫的 format() 内置函数(和扩展 format() 方法的类 str )产生一个“格式化” 对象的字符串表示。 的 format_spec 参数是 一个字符串,该字符串包含格式化选项的描述。 的解释 format_spec 参数是类型 实现 __format__() 然而,大多数类 委托格式的内置类型,或者使用一个类似的 格式化选项的语法。

看到 格式规范迷你语言 标准格式语法的描述。

返回值必须是一个字符串对象。

object.__lt__(selfother)
object.__le__(selfother)
object.__eq__(selfother)
object.__ne__(selfother)
object.__gt__(selfother)
object.__ge__(selfother)

这些都是所谓的“富比较”的方法。 之间的对应关系 运算符的符号和方法名称如下: x < y 调用 x.__lt__(y) x < = y 调用 x.__le__(y) x = = y 调用 x.__eq__(y) x ! = y 调用 x.__ne__(y) x > y 调用 x.__gt__(y) x > = y 调用x.__ge__(y) 

丰富的比较方法可以返回单例 NotImplemented 如果真的 没有实现的操作对于给定的参数。 按照惯例, 假 和 真正的 返回一个成功的比较。 然而,这些 方法可以返回任何值,因此,如果比较运算符用于一个布尔值 上下文(如。 在的条件 如果 Python语句),将调用 布尔值() 价值判断的结果是真或假。

没有隐含的比较运算符之间的关系。 真相 的 x = = y 并不意味着 x ! = y 是假的。 因此,当 定义 __eq__() ,应该还定义 __ne__() 这样 运营商将如期执行。 看到段落 __hash__() 为 一些重要的笔记创建 hashable 对象支持 自定义比较操作,可用作为字典键。

没有swapped-argument版本的这些方法(当使用 离开论点不支持操作但正确的论点); 相反, __lt__() 和 __gt__() 是彼此的反射, __le__() 和 __ge__() 是彼此的倒影, __eq__() 和 __ne__() 是自己的倒影。

丰富的参数比较的方法永远不会强迫。

自动生成订购操作从一个根操作, 看到 总排序配方ASPN食谱 

对象。 __hash__ 自我 

由内置函数调用 hash() 对成员和操作 散列集合包括 集 frozenset dict 。 __hash__() 应该返回一个整数。 唯一的要求 属性对象也比较有相同的散列值,它是 建议以某种方式混合在一起(例如使用异或)的散列值 的对象的组件也参与比较的对象。

如果一个类没有定义一个 __eq__() 它不应该定义一个方法 __hash__() 操作;如果它定义了 __eq__() 但不是 __hash__() ,它的实例不会可用hashable物品 集合。 如果一个类定义的可变对象和实现一个 __eq__() 方法,它不应该实现__hash__() ,因为 hashable集合的实现需要一个关键的散列值 不变的(如果对象的散列值的变化,它将在错误的散列 桶)。

用户定义的类 __eq__() 和 __hash__() 方法 默认情况下,与他们,所有对象比较不平等(与自己除外) 和 x.__hash__() 返回 id(x) 

类的继承 __hash__() 方法从一个父类 变化的意义 __eq__() 这样没有返回的散列值 再适当的(例如,通过切换价值平等的概念 而不是默认的基于身份的平等)可以明确标志 自己是被unhashable设置 __hash__ 没有一个 在课堂上 定义。 这样做意味着不仅会提高一个实例的类 适当的 TypeError 当一个程序试图检索他们的散列 值,但他们也会正确地认定为unhashable时检查 isinstance(obj, collections.Hashable) (与类定义他们 自己的 __hash__() 显式地提高TypeError )。

如果一个类,重写 __eq__() 需要保留的实现 的 __hash__() 从一个父类,翻译必须被告知 显式地设置 __hash__ < ParentClass > .__hash__ 。 否则, 继承的 __hash__() 会被阻塞,就好像 __hash__ 被显式地设置 没有一个 

看到也 - r 命令行选项。

对象。 __bool__ 自我 

叫来实现真值测试和内置的操作 布尔值() ,应该返回 假 或 真正的 。 当这个方法不是 定义, __len__() 被调用时,如果它被定义,对象是什么 认为真正的结果是零。 如果一个类定义 __len__() 也不 __bool__() ,被认为是所有的实例 真实的。

自定义属性的访问 

以下方法可以定义自定义属性的意义 访问(使用,转让,或删除 x.name 为类实例)。

object.__getattr__(selfname)

时调用一个属性查询没有发现属性一般的地方 (即它不是一个实例属性也不是类树中发现的 自我 )。 的名字 是属性名。 此方法应该返回 (计算)的属性值或提高 AttributeError 例外。

注意,如果属性是发现通过正常的机制, __getattr__() 不叫。 (这是一个故意之间的不对称 __getattr__() 和 __setattr__() )。 这样做是对效率 原因,否则 __getattr__() 没有办法访问吗 其他属性的实例。 请注意,至少在实例变量, 你可以通过不插入任何假的完全控制实例中的属性值 字典(而是插入另一个对象)。 看到 __getattribute__() 方法下得到完全控制 对属性的访问。

object.__getattribute__(selfname) 

被称为无条件实现实例的属性访问 类。 如果类也定义了 __getattr__() ,后者将不会 称,除非 __getattribute__() 称之为明确或提出了一个 AttributeError 。 此方法应该返回属性值(计算) 或提高一个 AttributeError 例外。 为了避免无限 递归在这种方法中,其实现应该调用基类 具有相同名称的方法需要访问任何属性,例如, object.__getattribute__(自我, 名称) 

请注意 

 

该方法仍有可能绕过时查找的特殊方法 隐式的结果通过语言语法或内置函数调用。 看到 特殊的方法查找 

object.__setattr__(selfnamevalue)

时调用一个属性赋值是未遂。 这就是所谓的代替 正常的机制(即存储实例中的值字典)。 的名字 是属性名, 价值 是分配给它的值。

如果 __setattr__() 想要赋给实例属性,它应该 调用基类具有相同名称的方法,例如, object.__setattr__(自我, 的名字, 值) 

object.__delattr__(selfname)
就像 __setattr__() 但对于属性删除而不是任务。 这 只能实现如果 ▽ obj.name 有意义的对象。
object.__dir__(self) 
时调用 dir() 被称为对象。 必须返回列表。

实现描述符 

下面的方法只适用于包含的类的实例 方法(所谓的 描述符 类)的出现 老板 类( 描述符必须在主人的字典类或类 词典对其父母)之一。 在下面的例子中,“属性” 指的是属性的名字是财产的所有者的关键 类的 __dict__ 

object.__get__(selfinstanceowner)
得到主人的属性类(class属性访问)或一个 这类的实例(实例属性访问)。 老板 永远是老板 类,而 实例 是实例的属性是通过, 或 没有一个 访问属性时通过 老板 。 这个方法 应该返回属性值(计算)或提高一个吗 AttributeError例外。
object.__set__(selfinstancevalue)
在一个实例上设置属性 实例 老板类 新值, 价值 
object.__delete__(selfinstance)
删除一个实例的属性 实例 所有者的类。

调用描述符 

一般来说,一个描述符是一个对象属性与“绑定行为”,一个 覆盖了的属性访问方法描述符 协议: __get__() __set__() __delete__() 。 如果任何 这些方法被定义为一个对象,它是一个描述符。

的默认行为属性访问,设置或删除 从一个对象的属性字典。 例如, a.x 有一个查找链 从 a.__dict__[' x '] ,然后 类型(一). __dict__[' x '] , 继续通过基类 类型(一) 不包括元类。

然而,如果抬头值是一个对象定义一个描述符 方法,那么Python可能覆盖默认行为和调用描述符 方法相反。 这发生在优先级链取决于哪个 描述符方法以及它们是如何被定义的。

描述符调用绑定的起点, a.x 。 如何 参数是依赖于组装 一个 :

直接调用
最简单和最常见的用户代码直接调用时调用 描述符方法: x.__get__(a) 
实例绑定
如果绑定到一个对象实例, a.x 转化为调用: 类型(一). __dict__[x].__get__(, 类型(a)) 
类绑定
如果绑定到一个类, A.x 转化为调用: A.__dict__[x].__get__(没有, 一) 
超级绑定
如果 一个 是一个实例 超级 ,然后绑定 超级(B, obj)m() 搜索 obj.__class__.__mro__ 的基类 一个 立刻前 然后调用描述符调用: A.__dict__[m].__get__(obj, obj.__class__) 

比如绑定描述符的优先调用取决于 描述符方法定义。 一个描述符可以定义任意组合 的 __get__() __set__() 和 __delete__() 。 如果它不 定义 __get__() 访问属性,那么将返回描述符 对象本身,除非有一个字典值对象的实例。 如果 描述符定义 __set__() 和/或 __delete__() ,它是一个数据 描述符;如果它定义了没有,它是一种数据描述符。 通常,数据 描述符定义 __get__() 和 __set__() ,而数据 描述符刚刚 __get__() 方法。 数据描述符 __set__() 和 __get__()定义总是覆盖的重新定义 实例字典。 相反,数据描述符可以覆盖 实例。

Python方法(包括 staticmethod() 和 classmethod() ) 作为数据描述符实现。 因此,可以定义和实例 覆盖方法。 这允许单个实例收购行为 不同于其他相同的类的实例。

的 财产() 功能被实现为一个数据描述符。 因此, 实例不能覆盖一个属性的行为。

 __slots__ 

默认情况下,类的实例都有一本字典存储为属性。 这 浪费空间对象有很少的实例变量。 的空间 消费可以成为急性当创建大量的实例。

可以覆盖默认的定义 __slots__ 在一个类的定义。 的 __slots__ 声明需要一系列实例变量和储备 足够的空间在每个实例为每个变量值。 空间是 保存,因为 __dict__ 不是为每个实例创建。

对象。 __slots__ 
这类变量可以被分配一个字符串,iterable或序列 字符串实例所使用的变量名。 如果定义在一个 类, __slots__ 声明的变量,防止储备空间 自动创建的 __dict__ 和 __weakref__ 为每一个实例。
 使用说明 __slots__ 
  • 当从一个类继承 __slots__ __dict__ 的属性 该类总是触手可及,所以 __slots__ 定义的 子类是没有意义的。
  • 没有一个 __dict__ 实例变量,不能分配新变量 中列出的 __slots__ 定义。 试图分配未上市 变量名了 AttributeError 。 如果动态分配的新 变量,然后添加 “__dict__” 字符串的顺序 的 __slots__ 声明。
  • 没有一个 __weakref__ 为每个实例变量,类定义 __slots__ 不支持弱引用的实例。 如果弱引用 支持是必要的,然后添加 “__weakref__” 字符串的序列 __slots__ 声明。
  • __slots__ 通过创建描述符类级别实现吗 ( 实现描述符 为每一个变量名)。 因此,类属性 不能用于设置实例变量所定义的默认值 __slots__ ;否则,类属性将覆盖描述符 任务。
  • 的行动 __slots__ 声明仅限于类的地方 定义的。 因此,将会有一个子类 __dict__ 除非他们还定义 __slots__ (必须只包含任何的名字 额外的 槽)。
  • 如果一个类定义了一个槽中定义一个基类,实例变量 基类定义的位置不可访问(除了通过检索 直接从基类描述符)。 这个呈现的意义 程序定义。 在未来,检查可能被添加到防止这种情况。
  • 非空的 __slots__ 不工作类源自“变长” 内置类型等 int str 和 元组 
  • 任何non-string iterable可能分配到 __slots__ 。 映射也可以 使用;然而,在未来,特殊的意义可能分配到的值 对应于每个键。
  • __class__进行 作业只有两类有相同的工作 __slots__ 

创建自定义类 

默认情况下,类是使用 类型() 。 一个类定义 读到一个单独的命名空间和类名绑定到的价值 的结果 类型(名称、 基地, dict) 

阅读类定义时,如果一个可调用的 元类 关键字参数 通过在类定义之后,将给出的可调用的 叫代替 类型() 。 如果其他关键字参数传递,他们 也会传递到元类。 这允许类或函数 写这显示器或改变类的创建过程:

  • 修改字典之前被创建的类的类。
  • 返回另一个类的一个实例——本质上执行的角色 工厂函数。

这些步骤必须在元类的执行 __new__() 方法 - - - - - - type.__new__() 可以从这个方法调用创建一个类 不同的属性。 下面的例子添加一个新元素 字典之前创建的类:

class metacls(type):
    def __new__(mcs, name, bases, dict):
        dict['foo'] = 'metacls was here'
        return type.__new__(mcs, name, bases, dict)

你也当然可以覆盖其他类方法(或添加新方法); 定义一个自定义的例子 __call__() 在元类允许定义方法 行为类,如不是创建一个新的实例。

如果元类 __prepare__() 属性(通常是作为一个实现 类或静态方法),之前它被称为类身体评估 类的名称和一个元组的基础参数。 它应该返回 支持的对象映射接口,将用于存储 类的命名空间。 默认是一个普通的字典。 这可能是使用, 例如,跟踪订单的类中声明的属性 返回一个有序字典。

适当的元类是由以下优先规则:

  • 如果 元类 关键字参数传递的基地,就使用它。
  • 否则,如果至少有一个基类,它使用元类。
  • 否则,默认元类( 类型 使用)。

潜在的使用元类是无穷无尽的。 一些想法 探索包括日志、界面检查,自动代表团、自动 产权创造、代理、框架和自动资源 锁定/同步。

这里是一个元类的一个例子,它使用一个 collections.OrderedDict 记得类成员定义的顺序:

class OrderedClass(type):

     @classmethod
     def __prepare__(metacls, name, bases, **kwds):
        return collections.OrderedDict()

     def __new__(cls, name, bases, classdict):
        result = type.__new__(cls, name, bases, dict(classdict))
        result.members = tuple(classdict)
        return result

class A(metaclass=OrderedClass):
    def one(self): pass
    def two(self): pass
    def three(self): pass
    def four(self): pass

>>> A.members
('__module__', 'one', 'two', 'three', 'four')

当定义的类 一个 被执行,流程开始 调用元类的 __prepare__() 方法返回一个空的 collections.OrderedDict 。 该映射的方法和记录 的属性 一个 因为它们的类中定义语句。 一旦这些定义,执行命令词典是完全填充 元类的 __new__()方法调用。 该方法构建 新类型和保存命令字典键属性 被称为 成员 

自定义子类实例和检查 

下面的方法是用于覆盖的默认行为 isinstance() 和 issubclass() 内置函数。

特别是,元类 abc.ABCMeta 实现这些方法 为了允许添加抽象基类(abc)作为“虚拟基地 类”到任何类或类型(包括内置类型),包括其他 abc。

class.__instancecheck__(selfinstance) 
返回true,如果 实例 应该被视为一个(直接或间接) 的实例 类 。 如果定义,叫来实现 isinstance(例如, 类) 
class.__subclasscheck__(selfsubclass) 
返回true,如果 子类 应该被视为一个(直接或间接) 的子类 类 。 如果定义,叫来实现 issubclass(子类, 类) 

注意,这些方法都是抬头类的类型(元)。 他们 不能定义为类方法在实际的类。 这是一致的 特别的方法被称为实例的查找,只在这 情况下,类本身就是一个实例。

另请参阅 

引入抽象基类
包括自定义的规范 isinstance() 和 issubclass() 行为 __instancecheck__() 和 __subclasscheck__() 这个功能的动机 添加抽象基类(请参阅 美国广播公司 模块) 语言。

模拟可调用对象 

object.__call__(self[, args...])

时调用实例”被称为“功能;如果这个方法定义, x(__arg1、 最长, …) 是一个缩写 x.__call__(__arg1、 最长, …) 

 模拟容器类型 

以下方法可以定义实现容器对象。 容器 通常序列(如列表或元组)或映射(如字典), 但也可以代表其他容器。 第一组使用方法 模仿一个序列或模仿一个映射,不同之处在于, 一个序列,容许键应该是整数 的 < = 在哪里 N序列的长度,或切片对象,定义一个 项目的范围。 它也建议映射提供了方法 键() 值() 项目() get() clear() setdefault() pop() popitem() 副本() update() 行为类似于Python的标准字典 对象。 的 集合 模块提供了一个 MutableMapping 抽象基类来帮助从一组基础的创建这些方法 __getitem__() __setitem__() __delitem__() 键() 。 可变序列应该提供方法 append() count() index() 扩展() insert() pop() remove() 反向() 和 sort() ,像Python标准列表对象。 最后, 序列类型应该实现(即连接)和 乘法(即重复)通过定义的方法 __add__() __radd__() __iadd__() __mul__() __rmul__() 和 __imul__() 下面描述;他们不应该定义其他数值 操作符。 建议实现映射和序列 __contains__() 方法允许高效的使用 在 运营商; 映射, 在 应该为序列,搜索映射的键;它应该吗 搜索的值。 映射和进一步的建议 序列实现 __iter__() 允许高效的迭代方法 通过对映射,容器; __iter__() 应该是一样的吗 键() ;因为序列,它应该遍历值。

object.__len__(self)

实现内置函数 len() 。 应该返回长度 的对象,一个整数 > = 0。 同样,一个没有定义一个对象 __bool__() 的方法和 __len__() 方法返回0 在布尔上下文被认为是错误的。

请注意 

 

切片是专门用以下三种方法来完成的。 这样的电话

a[1:2] = b

a[slice(1, 2, None)] = b

等等。 缺失的部分物品总是填写 没有一个 

object.__getitem__(selfkey)

实施评价 自我(例子) 。 序列类型, 接受键应该是整数和片对象。 注意,特别 解释负索引(如果类希望模仿一个序列 的类型) __getitem__() 方法。 如果 关键 是一个不正确的 类型, TypeError 可能提高;如果索引值外设置的 的序列(在任何特殊的解释-值), IndexError 应该提高。 映射类型,如果 关键 丢失(不 在容器), KeyError 应该提高。

请注意 

为 循环预计一个 IndexError 将提高违法吗 索引,允许适当的检测序列的结束。

object.__setitem__(selfkeyvalue)
叫来实现任务 自我(例子) 。 注意一样的 __getitem__() 。 如果这只应执行映射 对象支持改变键的值,或者添加新的键,或 对序列元素可以被取代。 相同的异常应该提高 以不当 关键 值的 __getitem__() 方法。
object.__delitem__(selfkey)
实现删除 自我(例子) 。 注意一样的 __getitem__() 。 如果这只应执行映射 对象支持删除键,或序列如果元素可以被删除 从序列。 相同的异常应该提高不当 关键 值的 __getitem__() 方法。
object.__iter__(self)

调用此方法时,迭代器需要一个容器。 这个方法 应该返回一个新的迭代器对象,可以遍历所有的对象 容器。 对映射,它应该遍历容器的钥匙,和 还应该提供的方法 键() 

迭代器对象还需要实现这个方法,他们需要回报 他们自己。 迭代器对象的更多信息,请参阅 迭代器类型 

object.__reversed__(self) 

(如果存在) 逆转() 内置的实现 反向迭代。 它应该返回一个迭代的新的迭代器对象 在相反的顺序容器中的所有对象。

如果 __reversed__() 不提供方法, 逆转() 内置序列将退回使用协议( __len__() 和 __getitem__() )。 支持的协议序列应该的对象 只提供 __reversed__() 如果他们能提供一个实现 这是比提供的一个更加有效 逆转() 

会员测试操作符( 在 和 不 在 )通常是 通过序列作为迭代实现。 然而,容器对象 以下特殊方法提供一个更有效的实现 也不需要的对象是一个序列。

object.__contains__(selfitem)

实现会员测试操作符。 应该返回true,如果 项 是在 自我 否则,则返回false。 映射对象,这应该考虑 键的映射而不是值或重点项目对。

不定义的对象 __contains__() 首先,加入测试 尝试通过迭代 __iter__() ,那么旧的迭代序列 协议通过 __getitem__() ,请参阅 本部分的语言 参考 

模拟数字类型 

可以定义下列方法来模拟数字对象。 方法 对应的操作由特定种类的不支持 数量(如实现。 非整型数据,逐位操作) 未定义的。

object.__add__(selfother)
object.__sub__(selfother)
object.__mul__(selfother)
object.__truediv__(selfother)
object.__floordiv__(selfother)
object.__mod__(selfother)
object.__divmod__(selfother)
object.__pow__(selfother[, modulo])
object.__lshift__(selfother)
object.__rshift__(selfother)
object.__and__(selfother)
object.__xor__(selfother)
object.__or__(selfother)

这些方法被称为实现二进制算术运算( - - - - - - / / divmod() 战俘() * * < < > > )。 例如,对表达式求值 ,在那里 是一个类的实例,有吗 __add__() 方法, x.__add__(y) 被称为。 的 __divmod__() 方法应该是 相当于使用 __floordiv__() 和 __mod__() ,它不应该 有关 __truediv__() 。 请注意, __pow__() 应定义 接受一个可选的第三个参数,如果三元的内置版本 战俘() 功能是被支持。

如果其中一个不支持提供的操作的方法 参数,它应该返回 NotImplemented 

object.__radd__(selfother)
object.__rsub__(selfother)
object.__rmul__(selfother)
object.__rtruediv__(selfother)
object.__rfloordiv__(selfother)
object.__rmod__(selfother)
object.__rdivmod__(selfother)
object.__rpow__(selfother)
object.__rlshift__(selfother)
object.__rrshift__(selfother)
object.__rand__(selfother)
object.__rxor__(selfother)
object.__ror__(selfother)

这些方法被称为实现二进制算术运算( - - - - - - / / divmod() 战俘() * * < < > > 操作数)和反射(交换)。 如果调用这些函数只有左操作数不支持 相应的操作和操作数是不同的类型。[2] 为 实例,对表达式求值 - - - - - - ,在那里 是一个实例 一个有一个的类 __rsub__() 方法, y.__rsub__(x) 叫如果 x.__sub__(y) 返回 NotImplemented 

请注意,三元 战俘() 不会打电话 __rpow__() ( 强制规则会变得太复杂)。

请注意 

 

如果右操作数的类型的子类左操作数的类型 子类提供了反映操作方法,该方法将 之前被称为左操作数的non-reflected方法。 这个动作允许 子类覆盖他们的祖先操作。

object.__iadd__(selfother)
object.__isub__(selfother)
object.__imul__(selfother)
object.__itruediv__(selfother)
object.__ifloordiv__(selfother)
object.__imod__(selfother)
object.__ipow__(selfother[, modulo])
object.__ilshift__(selfother)
object.__irshift__(selfother)
object.__iand__(selfother)
object.__ixor__(selfother)
object.__ior__(selfother)
这些方法被称为实现增强算术作业 ( + = - = * = / = / / = % = * * = < < = > > = & = ^ = | = )。 这些方法应该试图做手术 就地(修改 自我 )和返回结果(这可能是,但是 不是必须, 自我 )。 如果没有定义一个特定的方法,增强 赋值回落到正常的方法。 例如,执行 声明 + = ,在那里 是一个类的实例,有吗 __iadd__() 方法, x.__iadd__(y) 被称为。 如果 是一个实例 没有定义的一个类 __iadd__() 方法, x.__add__(y) y.__radd__(x) 被认为是,与评价 
object.__neg__(self)
object.__pos__(self)
object.__abs__(self)
object.__invert__(self)

实现一元算术运算( - - - - - - abs() 和 )。

object.__complex__(self)
object.__int__(self)
object.__float__(self)
object.__round__(self[, n])

实现内置函数 复杂的() int() 浮动() 和 圆的() 。 应该返回一个值 适当的类型。

对象。 __index__ 自我 
叫来实现 operator.index() 。 也称为每当Python的需要 一个整数对象(如在切片,或内置的 本() 十六进制() 和 10月() 功能)。 必须返回一个整数。

 与声明上下文联系

一个 上下文管理器 是一个对象,定义了运行时上下文 当执行一个建立 与 声明。 上下文管理器 处理进入和退出,所需的运行时上下文 执行的代码块。 经理通常使用的调用上下文 与 语句(描述的部分 与声明 ),但也可以 使用通过直接调用它们的方法。

上下文管理的典型应用包括保存和恢复各种 全局状态,锁定和释放资源,关闭打开的文件等。

上下文管理器的更多信息,请参阅 上下文管理器类型 

object.__enter__(self) 
进入运行时上下文相关对象。 的 与 声明 将这个方法的返回值绑定到目标(s)中指定的吗 作为 条款的声明,如果任何。
object.__exit__(selfexc_typeexc_valuetraceback) 

退出运行时上下文相关对象。 参数描述 异常导致上下文退出。 如果上下文是退出 没有一个例外,所有的三个参数 没有一个 

如果提供的是一个例外,方法希望抑制异常 (即。 ,防止它传播),它应该返回真值。 否则,异常处理通常在退出这个方法。

请注意, __exit__() 方法不应该reraise传入异常; 这是调用者的责任。

 特殊的方法查找 

对于自定义类,隐含的调用特殊的方法是唯一的保证 正常工作如果上定义一个对象的类型,而不是对象的实例 字典。 这种行为就是下面的代码的原因提出了一个 例外:

>>> class C:
...     pass
...
>>> c = C()
>>> c.__len__ = lambda: 5
>>> len(c)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: object of type 'C' has no len()

这种行为背后的基本原理在于一些特殊的方法 作为 __hash__() 和 __repr__() 所实现的所有对象, 包括类型对象。 如果这些方法使用的隐式查找 传统的查找过程,调用类型对象时,他们将会失败 本身:

>>> 1 .__hash__() == hash(1)
True
>>> int.__hash__() == hash(int)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: descriptor '__hash__' of 'int' object needs an argument

错误地试图调用类的方法以这种方式不限 有时被称为“元类混乱”,并避免被绕过 实例时查找特殊方法:

>>> type(1).__hash__(1) == hash(1)
True
>>> type(int).__hash__(int) == hash(int)
True

除了绕过任何实例的属性 正确性,查找通常也绕过了隐含的特殊方法 __getattribute__() 即使对象的元类的方法:

>>> class Meta(type):
...    def __getattribute__(*args):
...       print("Metaclass getattribute invoked")
...       return type.__getattribute__(*args)
...
>>> class C(object, metaclass=Meta):
...     def __len__(self):
...         return 10
...     def __getattribute__(*args):
...         print("Class getattribute invoked")
...         return object.__getattribute__(*args)
...
>>> c = C()
>>> c.__len__()                 # Explicit lookup via instance
Class getattribute invoked
10
>>> type(c).__len__(c)          # Explicit lookup via type
Metaclass getattribute invoked
10
>>> len(c)                      # Implicit lookup
10

绕过 __getattribute__() 机械以这种方式 提供了重要的空间内优化速度 翻译,在一些灵活性的处理成本 特殊方法(特殊的方法 必须 设置类 对象本身为了始终调用解释器)。

脚注

 可能在某些情况下改变一个对象的类型,在某些 控制条件。 这通常不是一个好主意,因为它可以 导致一些非常奇怪的行为如果处理不正确。

对于相同类型的操作数,它假定如果non-reflected方法 (如 __add__() )不支持操作失败,这就是为什么 反映方法不叫。

posted @ 2016-04-26 09:59  七月的尾巴_葵花  阅读(209)  评论(0编辑  收藏  举报