python3.x随手笔记2
对象,价值观和类型
对象 Python的抽象的数据。 所有的数据在一个Python程序 表示对象或对象之间的关系。 (在某种意义上,在 符合冯诺依曼模型的代码也“存储程序计算机” 由对象。)
每一个对象都有一个身份,一个类型和一个值。 一个对象的 身份 从来没有 改变一旦被创建,你可能认为这是对象的地址 内存。 “ 是 “运营商比较两个对象的身份, id() 函数返回一个整数代表其身份(目前 实现为其地址)。 一个对象的 类型 也是不变的。 [1] 一个对象的类型决定了操作对象支持(如。 :“ 它有长度吗?”),也定义了对象的可能值 类型。 的 类型() 函数返回一个对象的类型(这是一个对象 本身)。 的 价值 可以改变的对象。 对象,其价值可以 据说是改变 可变的 ,对象的值是不变的,一旦他们 创建了被称为 不可变的 。 (不可变容器对象的价值 包含对一个可变对象的引用可以改变时,后者的价值 改变;然而容器仍然被认为是不可变的,因为 它包含的对象集合不能改变。 所以,不变性 严格一样有一个不变的值,它是更微妙的)。 一个 对象的可变性是由其类型,例如,数字、字符串 和元组是不可变的,而词典和列表是可变的。
对象是从来没有明确地摧毁了;然而,当他们成为遥不可及的 他们可能被垃圾收集。 一个实现允许推迟垃圾 收集或者干脆省略它——它是一种实现质量 垃圾收集是如何实现的,只要没有对象收集 仍可及。
CPython的实现细节: CPython的目前使用引用计数和(可选)推迟了计划 相关的周期性检测垃圾,收集就大多数对象 当他们成为遥不可及的,但不能保证收集垃圾 包含循环引用。 看到的文档 gc 模块控制循环垃圾的收集信息。 其他实现不同和CPython的可能变化。 不依赖于立即终结的对象,当他们成为 遥不可及的(例:总是关闭文件)。
注意,使用实现的跟踪或调试设备 保持对象通常是收藏价值。 还要注意,抓住 一个异常与“ 试一试 … 除了 声明可能保持 对象还活着。
一些对象包含引用“外部”资源,比如文件或打开 窗户。 据悉,这些资源是当对象被释放 垃圾收集,但由于垃圾收集是没有保证的, 这样的对象也提供了一个显式释放外部资源的方式, 通常是一个 close() 方法。 项目是明确强烈推荐 这样的对象。 “ 试一试 … 最后 的声明 和“ 与 ”声明中提供便捷的方法。
一些对象包含对其他对象的引用,这些被称为 容器 。 容器的例子有元组、列表和字典。 的引用 集装箱的价值的一部分。 在大多数情况下,当我们谈论的价值 容器,我们暗示的值,而不是包含的对象的身份; 然而,当我们谈论一个容器的可变性,只有身份 立即包含的对象是隐含的。 所以,如果一个不可变的容器 (如一个元组)包含一个引用一个可变对象,如果它的值变化 可变的对象改变了。
对象的类型影响几乎所有方面的行为。 甚至的重要性 对象身份在某种程度上影响:对于不可变类型,操作 计算新值可能会返回一个引用任何现有的对象 可变对象相同的类型和值,而这是不允许的。 例如, 后 一个 = 1; b = 1 , 一个和 b 可能会或可能不会引用同一个对象 值,根据具体的实现方式,但之后 c = []; d = [] , c 和 d 保证指的是两个不同的,独特的,新吗 创建空的列表。 (注意, c = d = [] 分配相同的对象 c 和 d )。
标准的类型层次结构
下面是一个列表的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 可以通过检索 只读属性 z.real 和 z.imag 。
- 序列
-
这些代表有限点集被非负数字。 的 内置函数 len() 返回条目的数量的一个序列。 当 一个序列的长度 n ,该指数集包含数字0,1, …, n 1。 项 我 的序列 一个 被选中的 (我) 。
还支持序列切片: (i,j) 选择所有项目与索引 k 这样的 那 我 < = k < j 。 作为一个表达式时,一片 相同类型的序列。 这意味着指数集重新编号 它从0开始。
一些序列也支持“扩展切片”,第三个“步骤”参数: (我:j k): 选择所有项目的 一个 与指数 x 在哪里 x = 我 + n * k , n > = 0 和 我 < = x < j 。
序列是杰出的根据他们的可变性:
- 不变的序列
-
一个不可变的序列类型的一个对象不能改变一旦创建。 (如果 对象包含对其他对象的引用,这些其他对象 可变的,可能改变;然而,直接的对象集合 引用一个不可变对象不能改变。)
以下类型是不可变的序列:
- 字符串
-
字符串对象的项目是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 和 1.0 ),可以包含在一个只有一个人 集。
目前有两个内在的类型:
- 集
-
这些代表一组可变的。它们是由内置的 设置() 构造函数可以通过几种方法修改之后,等 add() 。
- 冰冻的集
-
这些代表一套不变的。它们是由内置的 frozenset() 构造函数。 作为一个frozenset是不可变的 hashable 再次,它可以使用另一个集合的一个元素,或作为 一个字典键。
- 映射
-
这些代表有限集的对象被任意指数集。 的 下标符号 一个[k] 选择项索引 k 从映射 一个 ,这可用于表情和作业的目标或 ▽ 语句。 内置的函数 len() 返回的数量 项的映射。
目前一个内在映射类型:
- 字典
-
这些代表有限集的对象索引近任意值。 的 只有类型的值包含列表或不能接受的作为键值 字典或其他可变类型相比,而不是价值 对象的身份,是有效实施的原因 字典需要一个关键的散列值保持不变。 数值类型使用 为数字键遵守正常的规则比较:如果两个数字比较 平等的(例如, 1 和 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__ 在参数列表的前面。 例如,当 C 是一个类包含一个定义一个函数 f() , x 是一个实例 C ,称 范(1) 是 相当于调用 出口(x, 1) 。
当一个对象实例方法来源于一个类方法对象, 存储在类实例 __self__ 会类 本身,以便调用 范(1) 或 由(1) 相当于 调用 f(C,1) 在哪里 f 是底层的函数。
注意,转换函数对象的实例方法 对象发生每次属性从实例中检索。 在 某些情况下,一个卓有成效的优化分配属性到本地 变量,称之为局部变量。 还要注意,这个 转换为用户定义函数只发生;其他可调用的 检索对象(和不可赎回所有对象) 转换。 同样重要的是要注意,用户自定义函数 类的属性的实例转换为绑定吗 方法,这 只有 当这个函数的一个属性 类。
- 发生器功能
-
使用的函数或方法 收益率 语句(参见 收益率的声明 )被称为 生成器函数 。 这样一个函数,当 调用时,总是返回一个迭代器对象可以用来执行 身体的功能:调用迭代器 __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 = 1 相当于 m.__dict__[x] = 1 。
特殊的只读属性: __dict__ 模块的名称空间是吗 字典对象。
CPython的实现细节: 因为字典CPython的清理模块,模块 字典将被清除时,模块即使超出范围 词典还住引用。 为了避免这种情况,复制字典 或保持周围的模块,而直接使用它的字典。
预定义的属性(可写): __name__ 模块的名字; __doc__ 是模块的文档字符串,还是 没有一个 如果 不可用; __file__ 文件的路径名来自哪个模块 是加载,如果从文件加载。 的 __file__ 属性不是 礼物给C模块静态链接到解释器; 扩展模块从一个共享库,动态加载路径名 共享库文件。
- 定制类
-
自定义类类型通常是由类定义(见部分 类定义 )。 一个由一个字典对象实现类都有一个名称空间。 类属性引用翻译在这本字典查找,例如, C.x 是翻译 C.__dict__[x] (尽管有很多 钩子允许的其他方式定位属性)。 当属性 没有找到名字,搜索仍在基类的属性。 这个搜索的基类使用的C3方法解析顺序 正确的行为即使在“钻石”继承结构的存在 哪里有多重继承路径回到共同的祖先。
当一个类属性(类的引用 C ),将产生一个 类方法对象,它转换成一个对象的实例方法 __self__ 属性 C 。 当它将产生一个静态的 方法对象,它转换成对象封装静态方法 对象。 参见 实现描述符 另一个属性的方式 从一个类检索可能不同于那些实际上包含在它 __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[我] 大概是等价的 来 类型(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 并不能直接调用 x.__del__() ——前者衰减 的引用计数 x ,而后者只是时调用 x 引用计数为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__(self, other)
- object.__le__(self, other)
- object.__eq__(self, other)
- object.__ne__(self, other)
- object.__gt__(self, other)
- object.__ge__(self, other)
-
这些都是所谓的“富比较”的方法。 之间的对应关系 运算符的符号和方法名称如下: 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__(self, name)
-
时调用一个属性查询没有发现属性一般的地方 (即它不是一个实例属性也不是类树中发现的 自我 )。 的名字 是属性名。 此方法应该返回 (计算)的属性值或提高 AttributeError 例外。
注意,如果属性是发现通过正常的机制, __getattr__() 不叫。 (这是一个故意之间的不对称 __getattr__() 和 __setattr__() )。 这样做是对效率 原因,否则 __getattr__() 没有办法访问吗 其他属性的实例。 请注意,至少在实例变量, 你可以通过不插入任何假的完全控制实例中的属性值 字典(而是插入另一个对象)。 看到 __getattribute__() 方法下得到完全控制 对属性的访问。
- object.__getattribute__(self, name)
-
被称为无条件实现实例的属性访问 类。 如果类也定义了 __getattr__() ,后者将不会 称,除非 __getattribute__() 称之为明确或提出了一个 AttributeError 。 此方法应该返回属性值(计算) 或提高一个 AttributeError 例外。 为了避免无限 递归在这种方法中,其实现应该调用基类 具有相同名称的方法需要访问任何属性,例如, object.__getattribute__(自我, 名称) 。
请注意
该方法仍有可能绕过时查找的特殊方法 隐式的结果通过语言语法或内置函数调用。 看到 特殊的方法查找 。
- object.__setattr__(self, name, value)
-
时调用一个属性赋值是未遂。 这就是所谓的代替 正常的机制(即存储实例中的值字典)。 的名字 是属性名, 价值 是分配给它的值。
如果 __setattr__() 想要赋给实例属性,它应该 调用基类具有相同名称的方法,例如, object.__setattr__(自我, 的名字, 值) 。
- object.__delattr__(self, name)
- 就像 __setattr__() 但对于属性删除而不是任务。 这 只能实现如果 ▽ obj.name 有意义的对象。
- object.__dir__(self)
- 时调用 dir() 被称为对象。 必须返回列表。
实现描述符
下面的方法只适用于包含的类的实例 方法(所谓的 描述符 类)的出现 老板 类( 描述符必须在主人的字典类或类 词典对其父母)之一。 在下面的例子中,“属性” 指的是属性的名字是财产的所有者的关键 类的 __dict__ 。
- object.__get__(self, instance, owner)
- 得到主人的属性类(class属性访问)或一个 这类的实例(实例属性访问)。 老板 永远是老板 类,而 实例 是实例的属性是通过, 或 没有一个 访问属性时通过 老板 。 这个方法 应该返回属性值(计算)或提高一个吗 AttributeError例外。
- object.__set__(self, instance, value)
- 在一个实例上设置属性 实例 老板类 新值, 价值 。
- object.__delete__(self, instance)
- 删除一个实例的属性 实例 所有者的类。
调用描述符
一般来说,一个描述符是一个对象属性与“绑定行为”,一个 覆盖了的属性访问方法描述符 协议: __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__ 的基类 一个 立刻前 B 然后调用描述符调用: 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__(self, instance)
- 返回true,如果 实例 应该被视为一个(直接或间接) 的实例 类 。 如果定义,叫来实现 isinstance(例如, 类) 。
- class.__subclasscheck__(self, subclass)
- 返回true,如果 子类 应该被视为一个(直接或间接) 的子类 类 。 如果定义,叫来实现 issubclass(子类, 类) 。
注意,这些方法都是抬头类的类型(元)。 他们 不能定义为类方法在实际的类。 这是一致的 特别的方法被称为实例的查找,只在这 情况下,类本身就是一个实例。
另请参阅
- 引入抽象基类
- 包括自定义的规范 isinstance() 和 issubclass() 行为 __instancecheck__() 和 __subclasscheck__() 这个功能的动机 添加抽象基类(请参阅 美国广播公司 模块) 语言。
模拟可调用对象
- object.__call__(self[, args...])
-
时调用实例”被称为“功能;如果这个方法定义, x(__arg1、 最长, …) 是一个缩写 x.__call__(__arg1、 最长, …) 。
模拟容器类型
以下方法可以定义实现容器对象。 容器 通常序列(如列表或元组)或映射(如字典), 但也可以代表其他容器。 第一组使用方法 模仿一个序列或模仿一个映射,不同之处在于, 一个序列,容许键应该是整数 k 的 0 < = k < N 在哪里 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__(self, key)
-
实施评价 自我(例子) 。 序列类型, 接受键应该是整数和片对象。 注意,特别 解释负索引(如果类希望模仿一个序列 的类型) __getitem__() 方法。 如果 关键 是一个不正确的 类型, TypeError 可能提高;如果索引值外设置的 的序列(在任何特殊的解释-值), IndexError 应该提高。 映射类型,如果 关键 丢失(不 在容器), KeyError 应该提高。
请注意
为 循环预计一个 IndexError 将提高违法吗 索引,允许适当的检测序列的结束。
- object.__setitem__(self, key, value)
- 叫来实现任务 自我(例子) 。 注意一样的 __getitem__() 。 如果这只应执行映射 对象支持改变键的值,或者添加新的键,或 对序列元素可以被取代。 相同的异常应该提高 以不当 关键 值的 __getitem__() 方法。
- object.__delitem__(self, key)
- 实现删除 自我(例子) 。 注意一样的 __getitem__() 。 如果这只应执行映射 对象支持删除键,或序列如果元素可以被删除 从序列。 相同的异常应该提高不当 关键 值的 __getitem__() 方法。
- object.__iter__(self)
-
调用此方法时,迭代器需要一个容器。 这个方法 应该返回一个新的迭代器对象,可以遍历所有的对象 容器。 对映射,它应该遍历容器的钥匙,和 还应该提供的方法 键() 。
迭代器对象还需要实现这个方法,他们需要回报 他们自己。 迭代器对象的更多信息,请参阅 迭代器类型 。
- object.__reversed__(self)
-
(如果存在) 逆转() 内置的实现 反向迭代。 它应该返回一个迭代的新的迭代器对象 在相反的顺序容器中的所有对象。
如果 __reversed__() 不提供方法, 逆转() 内置序列将退回使用协议( __len__() 和 __getitem__() )。 支持的协议序列应该的对象 只提供 __reversed__() 如果他们能提供一个实现 这是比提供的一个更加有效 逆转() 。
会员测试操作符( 在 和 不 在 )通常是 通过序列作为迭代实现。 然而,容器对象 以下特殊方法提供一个更有效的实现 也不需要的对象是一个序列。
- object.__contains__(self, item)
-
实现会员测试操作符。 应该返回true,如果 项 是在 自我 否则,则返回false。 映射对象,这应该考虑 键的映射而不是值或重点项目对。
不定义的对象 __contains__() 首先,加入测试 尝试通过迭代 __iter__() ,那么旧的迭代序列 协议通过 __getitem__() ,请参阅 本部分的语言 参考 。
模拟数字类型
可以定义下列方法来模拟数字对象。 方法 对应的操作由特定种类的不支持 数量(如实现。 非整型数据,逐位操作) 未定义的。
- object.__add__(self, other)
- object.__sub__(self, other)
- object.__mul__(self, other)
- object.__truediv__(self, other)
- object.__floordiv__(self, other)
- object.__mod__(self, other)
- object.__divmod__(self, other)
- object.__pow__(self, other[, modulo])
- object.__lshift__(self, other)
- object.__rshift__(self, other)
- object.__and__(self, other)
- object.__xor__(self, other)
- object.__or__(self, other)
-
这些方法被称为实现二进制算术运算( + , - - - - - - , * , / , / / , % , divmod() , 战俘() , * * , < < , > > , & , ^ , | )。 例如,对表达式求值 x + y ,在那里 x 是一个类的实例,有吗 __add__() 方法, x.__add__(y) 被称为。 的 __divmod__() 方法应该是 相当于使用 __floordiv__() 和 __mod__() ,它不应该 有关 __truediv__() 。 请注意, __pow__() 应定义 接受一个可选的第三个参数,如果三元的内置版本 战俘() 功能是被支持。
如果其中一个不支持提供的操作的方法 参数,它应该返回 NotImplemented 。
- object.__radd__(self, other)
- object.__rsub__(self, other)
- object.__rmul__(self, other)
- object.__rtruediv__(self, other)
- object.__rfloordiv__(self, other)
- object.__rmod__(self, other)
- object.__rdivmod__(self, other)
- object.__rpow__(self, other)
- object.__rlshift__(self, other)
- object.__rrshift__(self, other)
- object.__rand__(self, other)
- object.__rxor__(self, other)
- object.__ror__(self, other)
-
这些方法被称为实现二进制算术运算( + , - - - - - - , * , / , / / , % , divmod() , 战俘() , * * , < < , > > , & , ^ , | 操作数)和反射(交换)。 如果调用这些函数只有左操作数不支持 相应的操作和操作数是不同的类型。[2] 为 实例,对表达式求值 x - - - - - - y ,在那里 y 是一个实例 一个有一个的类 __rsub__() 方法, y.__rsub__(x) 叫如果 x.__sub__(y) 返回 NotImplemented 。
请注意,三元 战俘() 不会打电话 __rpow__() ( 强制规则会变得太复杂)。
请注意
如果右操作数的类型的子类左操作数的类型 子类提供了反映操作方法,该方法将 之前被称为左操作数的non-reflected方法。 这个动作允许 子类覆盖他们的祖先操作。
- object.__iadd__(self, other)
- object.__isub__(self, other)
- object.__imul__(self, other)
- object.__itruediv__(self, other)
- object.__ifloordiv__(self, other)
- object.__imod__(self, other)
- object.__ipow__(self, other[, modulo])
- object.__ilshift__(self, other)
- object.__irshift__(self, other)
- object.__iand__(self, other)
- object.__ixor__(self, other)
- object.__ior__(self, other)
- 这些方法被称为实现增强算术作业 ( + = , - = , * = , / = , / / = , % = , * * = , < < = , > > = , & = , ^ = , | = )。 这些方法应该试图做手术 就地(修改 自我 )和返回结果(这可能是,但是 不是必须, 自我 )。 如果没有定义一个特定的方法,增强 赋值回落到正常的方法。 例如,执行 声明 x + = y ,在那里 x 是一个类的实例,有吗 __iadd__() 方法, x.__iadd__(y) 被称为。 如果 x 是一个实例 没有定义的一个类 __iadd__() 方法, x.__add__(y) 和y.__radd__(x) 被认为是,与评价 x + y 。
- 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__(self, exc_type, exc_value, traceback)
-
退出运行时上下文相关对象。 参数描述 异常导致上下文退出。 如果上下文是退出 没有一个例外,所有的三个参数 没有一个 。
如果提供的是一个例外,方法希望抑制异常 (即。 ,防止它传播),它应该返回真值。 否则,异常处理通常在退出这个方法。
请注意, __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__() )不支持操作失败,这就是为什么 反映方法不叫。