3. 数据模型

3.1 对象、值和类型

对象是Python对数据的抽象。Python程序中所有数据都由对象或对象之间的关系表示。在某种意义上,为了和冯诺依曼存储程序计算机模型保持一致,代码和数据一样也是一个对象(冯诺依曼模型中提到,数据和程序都以0,1存储于存储器中)

每个对象都有一个ID,一个类型和一个值。对象一旦建立,它的ID永远不会改变;你可以认为它是该对象在内存中的地址。is’操作符比较两个对象的ID;id()函数返回一个表示对象ID 的整数(当前实现为对象的地址)。对象的类型也是不可变的。[1]对象的类型决定了对象支持的操作(例如,“它有长度吗?”)同时也定义了该种类型对象的可能的值。type()函数返回对象的类型(它本身也是一个对象)。某些对象的值可以改变。值可以改变的对象称为可变的;一旦建立,值就不可以改变的对象称为不可变的(包含可变对象引用的不可变容器对象在可变对象改变时是可以改变的;但容器仍被看作是不可变的, 因为它所包含的对象集合是不能变的。所以不可变对象与值不可变不是完全一样的,它更加微妙。)一个对象的可变性由它的类型决定;例如,数值、字符串和元组是不可变的,而字典和列表是可变的。

对象永远不会显式地销毁;但是当它们不可用时可以被当作垃圾回收。具体的实现可以推迟垃圾回收或完全忽略它 — 这是垃圾回收如何实现的特性问题,只要依然能访问的对象不被回收。

CPython 实现细节:CPython 当前使用引用计数机制与(可选)延迟检测循环连接的垃圾,它收集大部分对象一旦它们变得不可访问,但是不保证收集包含循环引用的垃圾。参考gc 模块的文档可以获得控制循环垃圾回收的信息。其它实现的行为与之不同并且CPython 的实现将来也可能会变化。不要依赖对象不可访问后会立即终结(例如:永远关闭文件)。

注意在执行期使用跟踪和调试功能,有可能使本来会回收的对象依然存活。还要注意使用‘try...except’语句捕获异常也可能保持对象一直存活。

有些对象包含对“外部”资源的引用,例如打开的文件或窗口。可以理解在对象被当作垃圾回收时这些资源也被释放,但因为垃圾回收不保证一定发生,这样的对象也提供显式的方法释放外部资源,通常是close()方法。强烈建议程序显式关闭这些对象。try...finally’语句提供了一个便利的方式来做这件事。

有些对象包含其它对象的引用;它们叫做容器容器的例子有元组,列表和字典。引用是容器的值的一部分。大多数情况下,当我们谈到一个容器的值时,我们是指值,而不是所包含的对象的ID;然而,当我们谈论容器对象的可变性的时候,就只是指被直接包含的对象的ID。因此,如果一个不可变对象(如元组)包含了一个可变对象的引用,那么当这个可变对象的值改变时它的值也发生改变。

对象的类型几乎影响对象的所有行为。在某种意义上甚至重要到影响对象的ID:对于不可变对象,计算新值的运算符可能实际上返回的是一个已存在的具有相同类型和值的对象的引用,而对于可变对象,这是不允许的。例如,在a = 1; b = 1之后,ab可能是或者可能不是引用同一个值为1的对象,这依赖于实现,但c = []; d = []之后,cd可以保证是引用两个不同的、唯一的、新创建的空列表。(注意c = d = []是把相同的对象赋给cd。)

3.2 标准类型的层次结构

以下是一份Python 内建类型的清单。扩展模块(无论是用C、Java还是用其它语言编写,依赖于具体实现)可以定义额外的类型。未来版本的Python 可能在这个类型层次结构中增加其它类型(例如:有理数、高效存储的整数数组,等等)。

下面有些类型的描述包含一个列出“特殊属性”的段落。这些属性提供访问具体的实现而不是作为一般的目的使用。它们的定义在未来可能会改变。

None

这种类型只有一个值。只有一个对象具有这个值。这个对象通过内建名字None访问。它在许多情况下用来表示没有值,例如,没有显式返回任何内容的函数会返回它。它的真值为假。

NotImplemented

这种类型只有一个值。只有一个对象具有这个值。这个对象通过内建名字NotImplemented访问。如果数值方法和复杂的比较方法提供了运算符却没有实现它,则可能返回这个值。(解释器会尝试反射的操作,或者其它退化的操作,依赖于具体的运算符。)它的真值为真。

Ellipsis

这种类型只有一个值。只有一个对象具有这个值。这个对象通过内建名字Ellipsis访问。它用于指示切片中出现的...语法。它的真值为真。

numbers.Number

它们由数值常量创建或者由算术运算符和内建的算术函数作为结果返回。数值对象是不可变的;一旦创建,它们的值永远不会改变。Python 的数值和数学上的数字关系当然是非常密切的,但受到计算机数值表达能力的限制。

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

numbers.Integral

它们表示数学上的整数集中的元素(包括正数和负数)。

有三种类型的整数:

普通整数

它们表示在-2147483648 至2147483647 范围之间的数。(这个范围可能会在CPU处理字长较长的机器上更大些,但不会更小。)如果某个运算的结果超出这个范围,结果会以长整数正常返回(在某些情况下,会抛出异常OverflowError)。对于起移位和掩码作用的运算,整数采用32位或更多位的二进制补码形式,并且不会对用户隐藏任何位。(就是说,所有4294967296个不同的比特组合对应于不同的值)。

长整数

长整数的表示的数值范围没有限制,只受限于可用的(虚拟内存)内存。对于起移位和掩码作用的运算,长整数采用二进制的形式,负数用二进制补码形式表示,给人的错觉是一个符号位向左无限扩展的字符串。

布尔值

布尔值表示假和真的真值。表示FalseTrue 的两个对象是仅有的布尔对象。布尔类型是普通整数的子类型,布尔值的行为在几乎所有环境下分别类似0和1。例外的情况是转换成字符串的时候分别返回字符串"False""True"

整数表示法的规则意在让负数的移位和掩码运算具有最有意义的解释,并且在普通整数和长整数之间转换时具有最少的意外。任何运算,只要它产生的结果在整数域之中,那么在长整数域或混合运算时将产生相同结果。域之间的转换对程序员是透明的。

numbers.Real (float)

这种类型表示机器级别的双精度浮点数。可接受的范围和溢出处理受限于底层的机器体系结构(和C或者Java的实现)。Python不支持单精度浮点数;使用两种精度浮点数的原因通常是节省处理器和内存的使用,但是相比Python中对象使用的开销是微不足道的,因此没有必要支持两种浮点数使语言变的复杂。

numbers.Complex

这种类型以一对机器级别的双精度浮点数表示复数。单精度浮点数同样可以用于复数类型。复数z的实部和虚部可以通过只读属性z.realz.imag获得。

序列

这种类型表示有限的顺序集合,用非负数索引。内建的函数len() 返回序列的元素个数。当序列的长度为n时,索引集合包含数字0, 1, ..., n-1。序列a的第i个元素通过a[i]来选择。

序列也支持切片:a[i:j]选择索引k满足i <= k < j的所有元素。作为表达式使用的时候,切片是一个相同类型的序列。这隐含着索引会从零开始重新计数。

某些序列还支持带有第三个“步长”参数的“扩展切片”:a[i:j:k] 选择a 中所有索引为x的 的元素,x = i + n*k, n >= 0i <= x < j

序列依据它们的可变性分为:

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

以下类型是不可变序列:

字符串

字符串由字符组成。没有单独的字符类型;字符用一个元素的字符串表示。字符以(至少)8 比特的字节表示。内建函数chr()ord()在字符和表示字节数值的非负整数之间转换。值在0-127 之间的字节通常表示相应的ASCII 值,但是对值的解释由程序决定。字符串数据类型也用于表示字节的数组,例如,保存从文件中读取的数据。

(在原生字符集不是ASCII 的系统上,字符串在内部可以使用EBCDIC 表示,只要函数chr()ord() 实现ASCII 和EBCDIC 之间的映射并且字符串的比较保留ASCII 顺序。或者可能有人能够提出一个更好的规则?)

Unicode

Unicode 对象的元素是Unicode 编码单元。一个Unicode 编码单元由一个元素的Unicode 对象表示并且可以保持16位或者32位的值表示一个Unicode 序数。(序数的最大值在sys.maxunicode中给出,并依赖Python 在编译的时候是如何配置的)Unicode 对象中可以表示代理对,并被当作两个单独的元素。内建的函数unichr()ord()在编码单元和表示定义在Unicode 标准3.0中Unicode 序数的非负整数之间转换。和其它编码之间相互转换可以通过Unicode 方法encode() 和内建的函数unicode()

元组

元组的元素可以是Python 的任何对象。两个或多个元素的元组由逗号分隔的一连串表达式形成。一个元素的元组(单元素集)可以在一个表达式的后面附加一个逗号形成(一个表达式自身不会形成一个元组,因为圆括号必须可以用来分组表达式)。一个空的元组可以由一个空的圆括号对形成。

可变序列

可变序列在生成之后可以修改。下标和切片表示法可以用于赋值和del(delete)语句的目标。

当前有两种内建的可变序列类型:

列表

列表的对象可以是Python 任何对象。列表由在方括号中放置一个逗号分隔的一连串表达式形成。(注意生成长度为0或1的列表没有特殊的情形。)

字节数组

一个字节数组对象是一个可变的数组。它们由内建的bytearray() 构造函数创建。除了可变性(因此不可哈希),字节数组提供和不可变字节对象同样的接口和功能。

扩展模块array提供另外一个可变序列类型的例子。

集合类型

这种类型表示无序的、有限的集合,集合中的元素是唯一的、不可变的对象。正因如此,它们不可以被任何下标索引。然而,它们可以迭代,内建函数len()返回集合中元素的个数。集合常见的用途有快速成员关系检测、从序列中删除重复元素和计算数学运算例如交集、并集、差集和对称差集。

集合的元素与字典的键一样,都适用不可变规则。注意,数值类型遵循正常的数值比较规则:如果两个数字相等(例如,11.0),其中只有一个可以包含在集合中。

当前有两种内建的集合类型:

集合

这种类型表示可变的集合。它们由内建函数set() 构造函数创建并可以在此之后通过几种方法修改,例如add()

固定集合

这种类型表示不可变集合。它们由内建函数frozenset()构造器创建。因为固定集合不可变且可以哈希,它可以作为另外一个集合的元素或者字典的键。

映射

这种类型表示由任意索引集合作索引的有限对象集合。下标表示法a[k] 从映射a 中选择由k 索引的元素;它可以用在表达式中并作为赋值或del语句的目标。内建函数len()返回映射中元素的个数。

当前只有一个内建映射类型:

字典

这种类型表示几乎可以由任何值索引的有限对象集合。仅有的不可以作为键值的是包含列表或者字典或者其它可变类型的值(这些类型通过值而不是对象ID比较),原因是字典的高效实现要求键的哈希值保持常量。注意,数值类型遵循正常的数值比较规则:如果两个数字相等(例如,11.0),那么它们可以互换地使用来索引同一个字典入口。

字典是可变的;它们可以通过{...} 表示法创建(参考Dictionary的显示一节)。

扩展模块dbmgdbmbsddb提供另外的映射类型的例子。

可调用类型

这些是可以使用函数调用操作(参考调用一节)的类型:

用户定义的函数

用户定义的函数对象由函数定义创建(参见函数定义一节)。它调用时参数列表的元素个数应该和函数的形式参数列表相同。

特殊属性:

属性 含义  
__doc__ func_doc 函数的文档字符串,如果没有就为None 可写
__name__ func_name 函数的名字。 可写
__module__ 函数定义所在的模块名,如果没有就为None 可写
__defaults__ func_defaults 为具有默认值的参数保存默认参数值的元组,如果没有参数具有默认值则为None 可写
__code__ func_code 表示编译后的函数体的代码对象。 可写
__globals__ func_globals 保存函数全局变量的字典的引用 — 函数定义所在模块的全局命名空间。 只读
__dict__ func_dict 支持任意函数属性的命名空间。 可写
__closure__ func_closure None 或者包含函数自由变量绑定的元组。 只读

大部分标有“可写”的属性会检查所赋值的类型。

版本2.4中的变化:func_name 成为如今可写的属性。

版本2.6中的变化:引入双下划线属性__closure__, __code__, __defaults__, 和__globals__作为对应的func_*属性的别名以向前兼容Python 3。

函数对象同样支持获取和设置任意属性,这可以用来附加元数据到函数中。常规属性可以用点号表示法获取和设置。注意当前的实现只在用户定义的函数上支持函数属性。未来可能支持内建函数上的函数属性。

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

用户定义的方法

用户定义的方法将类、类的实例(或者None)和任何可调用对象(通常是一个用户定义的函数)结合起来。

特殊的只读属性:im_self指类实例对象,im_func指函数对象;im_class对于绑定的方法指im_self的类,对于未绑定的方法指方法所在的类;__doc__指方法的文档(与im_func.__doc__相同);__name__指方法的名字(与im_func.__name__一样);__module__指方法定义所在模块的名字,如果没有则为None

版本2.2中的变化:im_self过去指的是定义方法的类。

版本2.6中的变化:为了Python 3向前的兼容性,im_func也可以使用__func__访问,im_self可以使用__self__访问。

方法也支持访问(但不能设置)底层函数对象的任何函数属性。

用户定义的方法对象可能在获取类(或类的一个实例)的一个属性的时候被创建,如果那个属性是用户定义的函数对象,或者一个未绑定的用户方法对象,或者一个类方法对象。如果那个属性是用户定义的方法对象,只有类和存储在原始方法对象中的类相同或者是其子类,才会创建一个新的方法对象;否则,使用初始的方法对象。

如果用户定义的方法是通过从类中获取用户定义的方法创建,它的im_selfNone并且方法对象称为未绑定的。如果是通过从类的某个实例中获取用户定义的方法创建,它的its im_self是那个实例,且方法对象称为绑定的。在任一种情况下,新方法的im_class 属性为那个类,im_func 属性为原始的函数对象。

如果用户定义的方法是通过从类或者类实例中获取另外一个方法对象来创建,新的实例的im_func 属性不是原始的方法对象而是它的im_func 属性,除此之外其行为和处理函数对象时一样。

如果用户定义的方法对象通过从类或者实例中获取类方法对象创建,它的im_self 属性为类本身,且它的im_func 属性为类方法底层的函数对象。

当调用未绑定的方法对象时,调用的是底层的函数(im_func),有个限制是第一个参数必须是合适的类(im_class) 或其子类的实例。

当调用绑定的用户定义方法时,调用的是底层的函数(im_func),同时在参数列表的前面插入类的实例(im_self)。例如,当C 是一个类,包含函数f() 的定义,并且xC 的一个实例,调用x.f(1) 等同于调用C.f(x, 1)

如果用户定义的方法对象继承自类方法对象,存储在im_self中的“类实例” 实际上将是类本身,因此调用x.f(1) 或者C.f(1) 等同于调用f(C,1)f是底层的函数。

注意从函数对象到(非绑定的或者绑定的)方法对象的转换在每次从类或对象获取属性时都会发生。在某些情况下,一个富有成效的优化是将属性赋值给一个局部变量然后调用那个局部变量。还要注意这种转换只有用户定义的函数会发生;其它可调用的对象(和所有不可调用的对象)在获取时不会转换。同样要注意如果用户定义的函数是类实例的属性不会被转换为绑定的方法;这种转换 发生在函数是类的属性的时候。

生成器函数

使用yield 语句(参考yield 语句一节)的函数或方法称为生成器函数这种函数,在调用的时候,总是返回一个可以用来执行函数体迭代器对象:调用迭代器的next() 方法将导致函数执行直到它使用yield语句提供一个值。当函数执行return 语句或者到达结束位置,会引发一个StopIteration 异常且迭代器将到达要返回的数据集合的末尾。

内建的函数

内建的函数对象是C函数的封装。内建函数的例子有len()math.sin()math 是标准的内建模块)。参数的数目和类型由C函数决定。特殊的只读属性:__doc__ 指函数的文档字符串,如果没有则为None__name__ 指函数名;__self__ 被设置为None(看看下一个属性);__module__ 指函数定义所在模块的名字,如果没有则为None

内建的方法

它实际上是内建函数的另一种形式的伪装,这次包含一个传递给C函数的对象作为隐式的参数。一个内建方法的例子是alist.append(),假设alist 是一个列表对象。在这种情况下,特殊的只读属性__self__ 设置为alist 对象。

类类型
类类型,或者“新式的类”是可调用的。这些对象通常作为工厂创建它们自己的实例,但是覆盖__new__()方法的类类型可以有所变化。调用的参数传递给__new__(),且在正常情况下再传递给__init__()来初始化新的实例。
经典的类

下面讲述类对象。当调用一个类对象时,会创建并返回一个新的类实例(下面也会讲述)。这隐含着会调用类的__init__() 方法,如果它有的话。任何参数都会传递给__init__() 方法。如果类没有__init__() 方法,那么调用类必须不带参数。

类的实例
下面讲述类的实例。类的实例只有当类具有__call__() 方法时才可以调用;x(arguments)x.__call__(arguments) 的简写。
模块

模块使用import 语句导入(参见import 语句一节)。模块对象有一个用字典对象实现的命名空间(这就是模块中定义的函数的func_globals 属性引用的字典)。属性的引用被转换成查询这个字典,例如m.x 等同于m.__dict__["x"]模块对象不包含初始化模块的代码对象(因为一旦初始化完成,它不会再需要了)。

属性的赋值会更新模块的命名空间字典,例如m.x = 1 等同于m.__dict__["x"] = 1

特殊的只读属性:__dict__ 指模块字典对象形式的命名空间。

CPython 实现细节:由于CPython 清除模块字典的方式,当模块离开作用域之外时,模块的字典将被清除即使字典仍然被引用。为了避免这一行为,复制一份模块的字典或者在直接使用模块字典的时候把模块保留着。

预定义的(可写)属性:__name__ 为模块的名字;__doc__ 指模块的文档字符串,如果没有则为None__file__ 为模块加载的文件路径,如果它是从文件中加载的话。与解释器静态连接的C模块没有__file__属性;对于从共享的库中动态加载的扩展模块,它是共享的库文件的路径。

类类型(新式类)和类对象(旧式/经典类)都由类定义创建(参见Class definitions 一节)。类有一个用字典对象实现的命名空间。类属性的引用被转换为这个字典的查询,例如,C.x 被转换为C.__dict__["x"](尽管新式类有若干特别的钩子允许其它方式定位属性)。当属性名在字典中没有找到时,会继续在基类中搜索。对于旧式的类,搜索是深度优先,按基类出现的顺序从左向右。新式的类使用更加复杂的C3 MRO,它的行为在即使出现‘diamond’继承时也是正确的,这时有多个继承路径可以回溯到同一个祖先。新式类使用的C3 MRO 的更多细节可以在2.3 版的文档中找到 http://www.python.org/download/releases/2.3/mro/

当类属性引用(例如类C)产生一个用户定义的函数对象或者未绑定的用户定义的方法对象,该方法对象相关联的的类是C或者它的基类,它被转换成一个未绑定的用户定义的方法对象,该方法对象的im_class 属性是C当它产生一个类方法对象时,它被转换成一个绑定的用户定义的方法对象,它的im_self 属性是C当它产生一个静态的方法对象时,它被转换成由该静态方法对象封装的对象。实现描述符 一节可以看到另外一种方式,从类中获取的属性可能与真正包含在__dict__中的不同(注意只有新式的类支持这种描述符)。

类属性的赋值将更新该类的字典,永远不会更新其基类的字典。

可以调用类对象(参考上面)产生一个类的实例(参考下面)。

特殊的属性:__name__ 是类的名字;__module__ 是类定义所在的模块名;__dict__ 是包含类命名空间的字典;__bases__ 是包含类的基类的元组,顺序为它们在基类列表中出现的顺序;__doc__ 是类的文档字符串,如果没有定义则为None。

类的实例

类的实例通过调用类对象创建(参见上文)。类的实例有一个用字典实现的命名空间,它是搜索属性引用的第一个地方。如果属性在那里没找到,但实例所属的类中有那个名字的属性,则继续在类的属性中查找。如果找到的是一个用户定义函数对象或者未绑定的用户定义的方法对象,而该方法对象关联的类是实例的类(称它为C)或者其基类,那么它被转换成一个绑定的用户定义的方法对象,这个方法对象的im_class 属性为Cim_self属性为这个实例。静态方法和类方法对象也会转换,就像它们已经从类C 中获取过一样;参见上文“类”。实现描述符 一节可以看到另外一种方式,通过实例获取类的属性可能与真正包含在类的__dict__中的不同。如果没有找到相应的类属性,并且对象的类有一个__getattr__()方法,那么这个方法会被调用以满足搜索。

属性的赋值和删除会更新实例字典,永远不会是类的字典。如果类有一个__setattr__() 或者__delattr__() 方法,那么会调用这个方法而不是直接更新实例的字典。

如果有特定名字的方法的定义,类实例可以伪装成数值,序列或者映射类型。参见特殊方法的名字 一节。

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

文件

文件对象表示打开的文件。文件对象可以由内建函数open()os.popen()os.fdopen() 和socket 对象的makefile()方法创建(或者其它扩展模块提供的函数或方法)。sys.stdinsys.stdoutsys.stderr文件对象 分别初始化为解释器的标准输入、输出和错误流。文件对象完全的文档参见文件对象 一节。

内部类型

解释器内部使用的一些类型会暴露给用户。它们的定义可能跟随解释器以后的版本变化,但是为了完整性,这里还是会提及。

代码对象

代码对象表示编译成字节的的可执行Python代码,或者字节码代码对象和函数对象的不同在于函数对象包含一个明确的该函数的全局变量的引用(函数定义所在的模块),而代码对象不包含上下文;另外默认参数值存储在函数对象中,而不是代码对象中(因为它们表示运行时计算的值)。和函数对象不同,代码对象是不可变的并且不会包含可变对象的引用(直接或间接的)。

特殊的只读属性:co_name 给出了函数的名字;co_argcount 是位置参数的数目(包括具有默认值的参数);co_nlocals 是函数使用的局部变量(包括参数);co_varnames 是一个包含局部变量名字的元组(从参数的名字开始);co_cellvars 是一个元组,包含嵌套的函数所引用的局部变量的名字;co_freevars 是一个包含自由变量名字的元组;co_code 是一个表示字节码指令序列的字符串;co_consts 是一个包含字节码使用的字面量的元组;co_names 是一个字节码使用的名字的元组;co_filename 是编译的代码所在的文件名;co_firstlineno 是函数第一行的行号;co_lnotab 是一个字符串,编码字节码偏移量到行号的映射(更多的细节参见解释器的源代码);co_stacksize 是要求的栈的大小(包括局部变量);co_flags 是一个整数,编码解释器的一系列标志。

co_flags 定义以下的标志位:如果函数使用*arguments 语法接收任意数目的位置参数,则置位成0x04如果函数使用**keywords 语法接收任意的关键字参数,则置位成0x08如果函数是一个生成器,则置位成0x20

未来功能的声明(from __future__ import division)同样使用co_flags 中的位来指明代码对象的编译是否启用某个特别的功能;如果函数的编译启用了未来的除法,则置位成0x2000在早期的Python 版本中,还使用过0x100x1000 标志位。

co_flags 中的其它位保留作内部使用。

如果代码对象表示一个函数,co_consts 中的第一个元素是函数的文档字符串,如果没有定义文档字符串则为None

帧对象

帧对象表示执行的帧。它们可以出现在回溯对象中(参见下面)。

特殊的只读属性:f_back 指向堆栈中的前一帧(朝调用的方向),如果这是堆栈最底部的帧则为Nonef_code 是帧中正在执行的代码对象;f_locals 是用于查询局部变量的字典;f_globals 用于全局变量;f_builtins 用与内建的(固有的)名字;f_restricted 是指示函数是否以受限的执行模式执行的标志;f_lasti 给出精确的指令(是一个代码对象的字节码字符串索引)。

特殊的可写属性:f_trace,如果不为None,则是源代码开始调用的函数(用于调试器);f_exc_typef_exc_valuef_exc_traceback 表示在父帧中最后发生的异常,只要在当前帧中曾经发生过异常(在所有其它情况下它们为None);f_lineno 帧当前的行号 — 从跟踪函数的内部写入这个值将跳转到指定的行(只用于最底部的帧)。调试器通过写入f_lineno可以实现跳转命令(又叫做Set Next 语句)。

回溯对象

回溯对象表示一个异常的栈回溯。回溯对象在发生异常时创建。当搜索异常处理器展开执行的栈时,在每一个展开层级,会把一个回溯对象会插入到当前回溯对象的前面。当进入异常处理器时,程序便可以访问栈回溯。(参见try 语句 一节。)它可以通过sys.exc_traceback,或者sys.exc_info() 返回的元组的第三个元素得到。倾向于后面一种方式,因为当程序使用多线程时,它也可以正确工作。当程序没有包含合适的处理函数时,栈回溯被写到(格式很漂亮)标准错误流;如果解释器是交互式的,用户还可以通过sys.last_traceback 得到它。

特殊的只读属性:tb_next 是栈回溯中的下一个层级(朝异常发生的那个帧的方向),如果没有下一级则为Nonetb_frame 指向当前层级的执行帧;tb_lineno 给出异常发生的行号;tb_lasti 指示精确的指令。如果异常发生在没有匹配的except 字句或者带有finally 字句的try 语句中,回溯中行号和最后的指令可能与帧对象的行号不同。

切片对象

切片对象在使用扩展的切片语法时用于表示切片。这种切片使用两个冒号,多切片或者省略号,例如,a[i:j:step]a[i:j, k:l],或a[..., i:j]它们还可以由内建的slice()函数创建。

特殊的只读属性:start 指下边界;stop 指上边界;step 指步长;每个属性在省略的情况下都为None这些属性可以使有任意类型。

切片对象支持下面一种方法:

slice.indices(self, length)

这个方法带有一个整数参数length,计算扩展切片的信息,如果切片对象应用到一个长度为length的序列将描述,该切片对象将描述的信息。它返回一个包含三个整数的元组;它们分别是startstop索引和步长step没有或者越界的索引以与正规的切片一致的方式处理。

在版本2.3 中新引入。

静态方法对象
静态方法对象提供一种可以绕过上面所讲的函数对象到方法对象转换的方法。静态方法对象可以是其它任何对象的封装,通常是用户定义方法。 当从一个类或者类实例获取静态方法对象时,返回的对象事实是封装过的对象, 这种对象不可以再进行其它转换。静态方法对象本身是不可调用的,尽管它所封装的对象通常是可调用的。静态方法对象由内建的staticmethod() 构造器创建。
类方法对象
类方法对象,就像静态方法对象,是对另一个对象的封装,它改变从类或者类实例中获取对象的方式。类方法对象在获取时的行为在上面有所描述,见“用户定义的方法”。类方法对象由内建的classmethod() 构造器创建。

3.3. 新式类和经典类

类和实例有两种类型:旧式(或者经典)类和新式类。

直到Python 2.1,旧式类是用户唯一可用的类型。(旧式)类的概念和类型的概念没有关系:如果x 是旧式类的实例,那么x.__class__ 表示x 的类,但是type(x) 永远是<type 'instance'>这反映了一个事实:所有的旧式实例,不管它们的类是什么,都是用同一个内建类型实现的,叫做instance

新式的类在Python 2.2 中引进以统一类和类型。新式类不多不少就是一个用户定义的类型。如果x 是新式类的实例,那么type(x)x.__class__ 通常是相同的。(但不能保证这点 - 新式类的实例允许覆盖x.__class__ 的返回值)。

引入新式类的主要动机是为了提供一个带有完整元模型的统一的对象模型。同时它还有许多实际的好处,比如继承大部分内建的类型和引入计算属性功能的“描述符”。

由于兼容性的原因,类在默认情况下仍然是旧式的。新式类通过指明另外一个新式类(例如 type)作为父类创建,如果不需要其它父类,也可以是“最顶级的类型” object除了type() 返回的内容不同,新式类和旧式类的行为在许多重要的细节上都有不同。其中一些变化对于新对象模型(the new object model)是基础性的,比如特殊方法调用的方式。其它是对之前由于兼容性不能实现“修复”,比如多继承情况下方法解析的顺序。

虽然这份手册目标是全面地覆盖Python’s 的类机制,但是在遇到新式类时可能仍然缺少某些方面。请参见http://www.python.org/doc/newstyle/ 获得更多的信息源。

旧式类在Python 3中被移除,只留下新式类的语义。

3.4. 特殊方法的名称

通过定义具有特殊名字的方法,类能够实现某些由特殊语法调用的操作(例如算术运算、下标和切片)。这是Python 运算符重载的方法,允许类针对语言运算符定义它们自己的行为。例如,如果某个类定义了一个名字为__getitem__()的方法,并且x 是这个类的实例,那么x[i]对于旧式类粗略等价于x.__getitem__(i),对于新式类等价于type(x).__getitem__(x, i)除非特别说明,当没有定义适当方法时,执行某个操作会抛出异常(一般是AttributeError 或者TypeError)。

在实现一个模拟内建类型的类时,重要的是模拟只需要达到对建模的对象有意义的程度。例如,对于获取单个元素某些序列可以工作,但抽取切片却是没有意义的。(一个例子是W3C的文档对象模型中的NodeList 接口。)

3.4.1. 基本的定制

object.__new__(cls[, ...])

用于创建类cls 的新实例。__new__()是一个静态方法(你不需要显式地这样声明),以实例的类为第一个参数。其余的参数是传递给对象构造表达式(即类的调用)的参数。__new__() 的返回值应该是新的对象实例(通常是cls 的一个实例)。

常见的实现是通过使用带有合适参数的 super(currentclass, cls).__new__(cls[, ...]) 调用超类的__new__() 方法创建类的一个新的实例,然后在返回之前有必要地修改新创建的类实例。

如果__new__() 返回cls 的一个实例,那么新实例的__init__() 方法将以类似__init__(self[, ...]) 的方式被调用,self 是新的实例,其它的参数和传递给__new__() 的参数一样。

如果__new__() 不是返回cls 的实例,那么新实例的__init__() 方法将不会被调用。

__new__() 主要是用来允许继承不可变类型(比如int、str 和tuple)以定制化实例的创建。它也经常在自定义的元类中被覆盖以定制类的创建。

object.__init__(self[, ...])

在实例(被__new__())创建完成时调用。The arguments are those passed to the class constructor expression. If a base class has an __init__() method, the derived class’s __init__() method, if any, must explicitly call it to ensure proper initialization of the base class part of the instance; for example: BaseClass.__init__(self, [args...]). As a special constraint on constructors, no value may be returned; doing so will cause a TypeError to be raised at runtime.

object.__del__(self)

Called when the instance is about to be destroyed. This is also called a destructor. If a base class has a __del__() method, the derived class’s __del__() method, if any, must explicitly call it to ensure proper deletion of the base class part of the instance. Note that it is possible (though not recommended!) for the __del__() method to postpone destruction of the instance by creating a new reference to it. It may then be called at a later time when this new reference is deleted. It is not guaranteed that __del__() methods are called for objects that still exist when the interpreter exits.

Note

del x不会直接调用x.__del__() —— 前者减少一个x的引用,后者只是在x的引用达到零时调用。Some common situations that may prevent the reference count of an object from going to zero include: circular references between objects (e.g., a doubly-linked list or a tree data structure with parent and child pointers); 发生异常的函数的调用栈的帧上对一个对象的引用(保存在sys.exc_info()[2]中的回溯使得调用栈的帧一直存活);或者在交互模型中引发未处理的异常的调用栈的帧上对一个对象的引用(保存在sys.last_traceback中的回溯使得调用栈的帧一直存活)。第一种情形只有显式地破坏这个环才能修复;the latter two situations can be resolved by storing None in sys.exc_traceback or sys.last_traceback. Circular references which are garbage are detected when the option cycle detector is enabled (it’s on by default), but can only be cleaned up if there are no Python-level __del__() methods involved. Refer to the documentation for the gc module for more information about how __del__() methods are handled by the cycle detector, particularly the description of the garbage value.

Warning

由于调用__del__() 方法的环境是不确定的,在它们执行时的异常会被忽略,而且会打印警告到sys.stderrAlso, when __del__() is invoked in response to a module being deleted (e.g., when execution of the program is done), other globals referenced by the __del__() method may already have been deleted or in the process of being torn down (e.g. the import machinery shutting down). For this reason, __del__() methods should do the absolute minimum needed to maintain external invariants. Starting with version 1.5, Python guarantees that globals whose name begins with a single underscore are deleted from their module before other globals are deleted; if no other references to such globals exist, this may help in assuring that imported modules are still available at the time when the __del__() method is called.

See also the -R command-line option.

object.__repr__(self)

Called by the repr() built-in function and by string conversions (reverse quotes) to compute the “official” string representation of an object. If at all possible, this should look like a valid Python expression that could be used to recreate an object with the same value (given an appropriate environment). If this is not possible, a string of the form <...some useful description...> should be returned. The return value must be a string object. If a class defines __repr__() but not __str__(), then __repr__() is also used when an “informal” string representation of instances of that class is required.

This is typically used for debugging, so it is important that the representation is information-rich and unambiguous.

object.__str__(self)

Called by the str() built-in function and by the print statement to compute the “informal” string representation of an object. This differs from __repr__() in that it does not have to be a valid Python expression: a more convenient or concise representation may be used instead. The return value must be a string object.

object.__lt__(self, other)
object.__le__(self, other)
object.__eq__(self, other)
object.__ne__(self, other)
object.__gt__(self, other)
object.__ge__(self, other)

New in version 2.1.

These are the so-called “rich comparison” methods, and are called for comparison operators in preference to __cmp__() below. The correspondence between operator symbols and method names is as follows: x<y calls x.__lt__(y), x<=y calls x.__le__(y), x==y calls x.__eq__(y), x!=y and x<>y call x.__ne__(y), x>y calls x.__gt__(y), and x>=y calls x.__ge__(y).

一个多元比较方法可以返回NotImplemented,如果给出的一对参数没有实现该操作。By convention, False and True are returned for a successful comparison. However, these methods can return any value, so if the comparison operator is used in a Boolean context (e.g., in the condition of an if statement), Python will call bool() on the value to determine if the result is true or false.

There are no implied relationships among the comparison operators. The truth of x==y does not imply that x!=y is false. Accordingly, when defining __eq__(), one should also define __ne__() so that the operators will behave as expected. 参见__hash__()的段落,关于创建hashable对象的重要注意事项,这种对象支持自定义比较操作并可用于字典的键。

There are no swapped-argument versions of these methods (to be used when the left argument does not support the operation but the right argument does); rather, __lt__() and __gt__() are each other’s reflection, __le__() and __ge__() are each other’s reflection, and __eq__() and __ne__() are their own reflection.

Arguments to rich comparison methods are never coerced.

To automatically generate ordering operations from a single root operation, see functools.total_ordering().

object.__cmp__(self, other)

如果没有定义多元比较(见上文),则调用比较操作。如果self < other,应该返回一个负整数;如果self == other,应该返回零;如果self > other,应该返回一个正整数。如果__cmp__()__eq__()__ne__()操作都没有定义,那么类的实例通过对象的ID(“地址”)比较。参见__hash__()的描述,关于创建hashable对象的重要注意事项,这种对象支持自定义比较操作并可用于字典的键。(Note: the restriction that exceptions are not propagated by __cmp__() has been removed since Python 1.5.)

object.__rcmp__(self, other)

Changed in version 2.1: No longer supported.

object.__hash__(self)

Called by built-in function hash() and for operations on members of hashed collections including set, frozenset, and dict. __hash__() should return an integer. 要求的唯一性质是比较起来相等的对象具有相同的哈希值;it is advised to somehow mix together (e.g. using exclusive or) the hash values for the components of the object that also play a part in comparison of objects.

If a class does not define a __cmp__() or __eq__() method it should not define a __hash__() operation either; 如果它定义了__cmp__()__eq__()方法但没有定义__hash__(),它的实例不可以用于哈希后的容器中。If a class defines mutable objects and implements a __cmp__() or __eq__() method, it should not implement __hash__(), since hashable collection implementations require that a object’s hash value is immutable (if the object’s hash value changes, it will be in the wrong hash bucket).

User-defined classes have __cmp__() and __hash__() methods by default; with them, all objects compare unequal (except with themselves) and x.__hash__() returns a result derived from id(x).

Classes which inherit a __hash__() method from a parent class but change the meaning of __cmp__() or __eq__() such that the hash value returned is no longer appropriate (e.g. by switching to a value-based concept of equality instead of the default identity based equality) can explicitly flag themselves as being unhashable by setting __hash__ = None in the class definition. Doing so means that not only will instances of the class raise an appropriate TypeError when a program attempts to retrieve their hash value, but they will also be correctly identified as unhashable when checking isinstance(obj, collections.Hashable) (unlike classes which define their own __hash__() to explicitly raise TypeError).

Changed in version 2.5: __hash__() may now also return a long integer object; the 32-bit integer is then derived from the hash of that object.

Changed in version 2.6: __hash__现在可以设置为None以显示地标志一个类的实例是不可哈希的。

object.__nonzero__(self)

Called to implement truth value testing and the built-in operation bool(); should return False or True, or their integer equivalents 0 or 1. When this method is not defined, __len__() is called, if it is defined, and the object is considered true if its result is nonzero. If a class defines neither __len__() nor __nonzero__(), all its instances are considered true.

object.__unicode__(self)

Called to implement unicode() built-in; should return a Unicode object. When this method is not defined, string conversion is attempted, and the result of string conversion is converted to Unicode using the system default encoding.

3.4.2. 自定义属性访问

可以定义下面的方法来自定义类实例的属性访问的含义(访问、赋值或者删除x.name)。

object.__getattr__(self, name)

Called when an attribute lookup has not found the attribute in the usual places (i.e. it is not an instance attribute nor is it found in the class tree for self). name is the attribute name. This method should return the (computed) attribute value or raise an AttributeError exception.

Note that if the attribute is found through the normal mechanism, __getattr__() is not called. (This is an intentional asymmetry between __getattr__() and __setattr__().) This is done both for efficiency reasons and because otherwise __getattr__() would have no way to access other attributes of the instance. Note that at least for instance variables, you can fake total control by not inserting any values in the instance attribute dictionary (but instead inserting them in another object). See the __getattribute__() method below for a way to actually get total control in new-style classes.

object.__setattr__(self, name, value)

Called when an attribute assignment is attempted. This is called instead of the normal mechanism (i.e. store the value in the instance dictionary). name is the attribute name, value is the value to be assigned to it.

If __setattr__() wants to assign to an instance attribute, it should not simply execute self.name = value — this would cause a recursive call to itself. Instead, it should insert the value in the dictionary of instance attributes, e.g., self.__dict__[name] = value. For new-style classes, rather than accessing the instance dictionary, it should call the base class method with the same name, for example, object.__setattr__(self, name, value).

object.__delattr__(self, name)

Like __setattr__() but for attribute deletion instead of assignment. This should only be implemented if del obj.name is meaningful for the object.

3.4.2.1. 新式类更多的属性访问

The following methods only apply to new-style classes.

object.__getattribute__(self, name)

Called unconditionally to implement attribute accesses for instances of the class. 如果类同时定义了__getattr__(),那么后者将不会被调用除非__getattribute__()显式调用它或者抛出一个AttributeError该方法应该返回(计算后的)值或者抛出一个AttributeError异常。为了避免在该方法中无限的递归,它的实现应该永远调用基类的同名方法以访问需要的任何属性,例如object.__getattribute__(self, name)

这个方法可能仍然被绕开当通过语言的语法或者内建函数的隐式调用的结果导致的查询特殊方法。参见新式类特殊的方法查找

3.4.2.2. 实现描述器

这些方法仅仅适用于那些包含这些方法的类(所谓的描述类)的一个实例,并出现在一个所有者类中(这些描述必须在所有者的类字典中或是在他自己父类的字典中)在下面的例子当中, “属性”指的是名称为属主类的__dict__中的键的属性。

object.__get__(self, instance, owner)

调用以获取所有者类的属性(可获得的类属性)或者是该类的一个实例属性(可获得的实例属性)owner始终是属主,instance是属性访问的实例,当属性通过owner访问时则为None这个方法应该返回(计算后)的属性值,或者引发一个AttributeError异常。

object.__set__(self, instance, value)

设置属主类的实例instance的属性为一个新值value

object.__delete__(self, instance)

删除属主类的实例instance的属性。

3.4.2.3. 调用描述器

一般情况下,描述器是一个具有“绑定行为”的对象属性,它的属性访问被描述器协议中的方法:__get__(), __set__()__delete__()覆盖。如果对象定义了这些方法中的任何一个,则称该对象是一个描述器。

属性访问的默认行为是从一个对象的字典中获取、设置或删除属性。例如,a.x的查找链从a.__dict__['x']开始,然后是type(a).__dict__['x'],接着继续搜寻出元类以外的type(a)的基类。

然而,如果要查找的值是一个定义了某个描述器方法的对象,那么Python可能覆盖默认的行为而调用描述器方法。它在优先链中发生的位置取决于定义了哪个描述器方法以及它们是如何调用的。注意,描述器只为新式对象或类(object()type()的子类)调用。

描述器调用的起点是一个绑定,a.x参数如何组装取决于a

Direct Call
The simplest and least common call is when user code directly invokes a descriptor method: x.__get__(a).
Instance Binding
If binding to a new-style object instance, a.x is transformed into the call: type(a).__dict__['x'].__get__(a, type(a)).
Class Binding
If binding to a new-style class, A.x is transformed into the call: A.__dict__['x'].__get__(None, A).
Super Binding
If a is an instance of super, then the binding super(B, obj).m() searches obj.__class__.__mro__ for the base class A immediately preceding B and then invokes the descriptor with the call: A.__dict__['m'].__get__(obj, obj.__class__).

Direct Call描述器可以定义__get__()__set__()__delete__()的任何组合。如果它没有定义__get__(),那么访问该属性将返回描述器对象自己除非该对象实例的字典中有一个值。如果描述器定义了__set__()和/或__delete__(),那么它是一个数据描述器;如果都没有定义,则是一个非数据描述器。通常,数据描述器__get__()__set__()两个都定义,而非数据描述器值定义__get__()方法。定义了__set__()__get__()的数据描述器始终覆盖实例字典中的重复定义。相反,非数据描述器可以被实例覆盖。

Python的方法(包括staticmethod()classmethod())实现为非数据描述器。因此,实例可以重新定义并覆盖这些方法。这允许相同类的每个实例个体获得与其它实例不同的行为。

property()函数实现为数据描述器。因此,实例不可以覆盖property的行为。

3.4.2.4. __slots__

默认情况下,旧式类和新式类都具有一个存储属性的字典。这对于具有非常多的实例属性的对象非常浪费空间。当创建大量的实例时,空间的消耗可能变得很严重。

在新式类的定义中,该默认行为可以通过定义__slots__覆盖。__slots__声明接受一个实例变量的序列并且在每个实例中只保留为每个变量保存一个值的空间。空间被省下来了是因为不会为每个实例创建__dict__

__slots__

这个类变量可以赋值为一个字符串、可迭代对象或者由实例使用的变量名组成的字符串序列。如果在新式类中定义,__slots__将保留空间给声明的变量且防止为每个实例自动创建__dict____weakref__

2.2版中新增。

使用__slots__的注意事项

  • 如果继承自一个没有__slots__的类,该类的__dict__属性将始终可以访问,所以在子类中定义__slots__毫无意义。

  • 没有__dict__变量,实例不可以给不在__slots__中定义的新变量赋值。尝试给没有列出的变量名赋值将引发AttributeError如果需要动态地给新的变量赋值,那么可以在__slots__的声明的字符串序列中增加'__dict__'

    2.3版中的变化:在此之前,添加'__dict__'__slots__声明中不会使得给没有在实例变量名称序列中列出的新属性赋值。

  • 因为每个实例都没有__weakref__变量,定义__slots__ 的类不支持对其实例的弱引用。如果需要支持弱引用,可以在__slots__声明的字符串序列中增加'__weakref__'

    2.3版中的变化:在此之前,添加'__weakref__'__slots__声明中并不会支持弱引用。

  • __slots__在类级别上实现,通过为每个变量名创建描述器(Implementing Descriptors)。结果,类属性不可以用于设置__slots__定义的实例变量的默认值;否则,该类属性将覆盖描述器的赋值。

  • __slots__定义的动作只限于它所定义的类。因此,子类将具有__dict__,除非它们也定义了__slots__(必须只能包含额外的slots名称)。

  • If a class defines a slot also defined in a base class, the instance variable defined by the base class slot is inaccessible (except by retrieving its descriptor directly from the base class). This renders the meaning of the program undefined. In the future, a check may be added to prevent this.

  • Nonempty __slots__ does not work for classes derived from “variable-length” built-in types such as long, str and tuple.

  • Any non-string iterable may be assigned to __slots__. Mappings may also be used; however, in the future, special meaning may be assigned to the values corresponding to each key.

  • __class__赋值只有在两个类具有相同的__slots__是才工作。

    2.6版中的变化:Previously, __class__ assignment raised an error if either new or old class had __slots__.

3.4.3. 自定义类的创建

By default, new-style classes are constructed using type(). A class definition is read into a separate namespace and the value of class name is bound to the result of type(name, bases, dict).

When the class definition is read, if __metaclass__ is defined then the callable assigned to it will be called instead of type(). This allows classes or functions to be written which monitor or alter the class creation process:

  • Modifying the class dictionary prior to the class being created.
  • Returning an instance of another class – essentially performing the role of a factory function.

These steps will have to be performed in the metaclass’s __new__() method – type.__new__() can then be called from this method to create a class with different properties. This example adds a new element to the class dictionary before creating the class:

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

You can of course also override other class methods (or add new methods); for example defining a custom __call__() method in the metaclass allows custom behavior when the class is called, e.g. not always creating a new instance.

__metaclass__

This variable can be any callable accepting arguments for name, bases, and dict. Upon class creation, the callable is used instead of the built-in type().

New in version 2.2.

恰当的元类由下面的过程规则决定:

  • 如果存在dict['__metaclass__'],则使用它。
  • 否则,如果至少有一个基类,则使用它的元类(首先寻找__class__属性,如果不存在则使用它的类型)。
  • 否则,如果存在一个名为__metaclass__的全局变量,则使用它。
  • 否则,按照旧的方式,使用经典的metaclass(type.ClassType)。

The potential uses for metaclasses are boundless. 使用场景包括日志打印、接口检查、自动托管、自动的属性创建、代理、框架和自动的资源加锁/同步。

3.4.4. 自定义实例和子类的检查

New in version 2.6.

The following methods are used to override the default behavior of the isinstance() and issubclass() built-in functions.

In particular, the metaclass abc.ABCMeta implements these methods in order to allow the addition of Abstract Base Classes (ABCs) as “virtual base classes” to any class or type (including built-in types), including other ABCs.

class.__instancecheck__(self, instance)

Return true if instance should be considered a (direct or indirect) instance of class. If defined, called to implement isinstance(instance, class).

class.__subclasscheck__(self, subclass)

Return true if subclass should be considered a (direct or indirect) subclass of class. If defined, called to implement issubclass(subclass, class).

Note that these methods are looked up on the type (metaclass) of a class. They cannot be defined as class methods in the actual class. This is consistent with the lookup of special methods that are called on instances, only in this case the instance is itself a class.

另请参阅

PEP 3119 - 引入抽象基类
包括通过__instancecheck__()__subclasscheck__()定制isinstance()issubclass()行为的说明,该功能推动了添加抽象基类(参见abc模块)到该语言中。

3.4.5. 模拟可调用对象

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

当实例作为函数“调用”时调用;如果定义了该方法,则x(arg1, arg2, ...)x.__call__(arg1, arg2, ...)的简写。

3.4.6. 模拟容器类型

The following methods can be defined to implement container objects. Containers usually are sequences (such as lists or tuples) or mappings (like dictionaries), but can represent other containers as well. The first set of methods is used either to emulate a sequence or to emulate a mapping; the difference is that for a sequence, the allowable keys should be the integers k for which 0 <= k < N where N is the length of the sequence, or slice objects, which define a range of items. (For backwards compatibility, the method __getslice__() (see below) can also be defined to handle simple, but not extended slices.) It is also recommended that mappings provide the methods keys(), values(), items(), has_key(), get(), clear(), setdefault(), iterkeys(), itervalues(), iteritems(), pop(), popitem(), copy(), and update() behaving similar to those for Python’s standard dictionary objects. The UserDict module provides a DictMixin class to help create those methods from a base set of __getitem__(), __setitem__(), __delitem__(), and keys(). 可变序列应该提供append(), count(), index(), extend(), insert(), pop(), remove(), reverse()sort(),就像Python标准的列表对象。Finally, sequence types should implement addition (meaning concatenation) and multiplication (meaning repetition) by defining the methods __add__(), __radd__(), __iadd__(), __mul__(), __rmul__() and __imul__() described below; they should not define __coerce__() or other numerical operators. It is recommended that both mappings and sequences implement the __contains__() method to allow efficient use of the in operator; for mappings, in should be equivalent of has_key(); for sequences, it should search through the values. It is further recommended that both mappings and sequences implement the __iter__() method to allow efficient iteration through the container; for mappings, __iter__() should be the same as iterkeys(); for sequences, it should iterate through the values.

object.__len__(self)

Called to implement the built-in function len(). Should return the length of the object, an integer >= 0. Also, an object that doesn’t define a __nonzero__() method and whose __len__() method returns zero is considered to be false in a Boolean context.

object.__getitem__(self, key)

Called to implement evaluation of self[key]. For sequence types, the accepted keys should be integers and slice objects. Note that the special interpretation of negative indexes (if the class wishes to emulate a sequence type) is up to the __getitem__() method. If key is of an inappropriate type, TypeError may be raised; if of a value outside the set of indexes for the sequence (after any special interpretation of negative values), IndexError should be raised. For mapping types, if key is missing (not in the container), KeyError should be raised.

Note

for loops expect that an IndexError will be raised for illegal indexes to allow proper detection of the end of the sequence.

object.__setitem__(self, key, value)

Called to implement assignment to self[key]. Same note as for __getitem__(). This should only be implemented for mappings if the objects support changes to the values for keys, or if new keys can be added, or for sequences if elements can be replaced. The same exceptions should be raised for improper key values as for the __getitem__() method.

object.__delitem__(self, key)

Called to implement deletion of self[key]. Same note as for __getitem__(). This should only be implemented for mappings if the objects support removal of keys, or for sequences if elements can be removed from the sequence. The same exceptions should be raised for improper key values as for the __getitem__() method.

object.__iter__(self)

This method is called when an iterator is required for a container. This method should return a new iterator object that can iterate over all the objects in the container. For mappings, it should iterate over the keys of the container, and should also be made available as the method iterkeys().

Iterator objects also need to implement this method; they are required to return themselves. For more information on iterator objects, see Iterator Types.

object.__reversed__(self)

Called (if present) by the reversed() built-in to implement reverse iteration. It should return a new iterator object that iterates over all the objects in the container in reverse order.

If the __reversed__() method is not provided, the reversed() built-in will fall back to using the sequence protocol (__len__() and __getitem__()). Objects that support the sequence protocol should only provide __reversed__() if they can provide an implementation that is more efficient than the one provided by reversed().

New in version 2.6.

The membership test operators (in and not in) are normally implemented as an iteration through a sequence. However, container objects can supply the following special method with a more efficient implementation, which also does not require the object be a sequence.

object.__contains__(self, item)

Called to implement membership test operators. Should return true if item is in self, false otherwise. For mapping objects, this should consider the keys of the mapping rather than the values or the key-item pairs.

For objects that don’t define __contains__(), the membership test first tries iteration via __iter__(), then the old sequence iteration protocol via __getitem__(), see this section in the language reference.

3.4.7. 模拟序列类型的额外方法

可以定义下面可选的方法以进一步模拟序列对象。不可变序列的方法应该至多值定义__getslice__()可变对象可以定义所有的三种方法。

object.__getslice__(self, i, j)

从2.0版后废弃: 支持类似__getitem__()方法的切片对象。(然后,CPython中的内建类型仍然实现了__getslice__()因此,当实现切片时你必须在子类中覆盖它。)

调用它以实现计算self[i:j]。返回的对象应该与self的类型相同。注意在切片表达式中省略的ij将分别被零或sys.maxint替换。如果在切片中使用了负索引,将在该索引加上序列的长度。如果该实例没有实现__len__()方法,将引发一个AttributeError无法保证这种方法调整过的索引仍然不是负数。大于序列长度的索引不会给修改。如果找不到__getslice__(),则创建一个切片对象并传递给__getitem__()

object.__setslice__(self, i, j, sequence)

调用它以实现对self[i:j]的赋值。ij的注意事项与__getslice__()相同。

该方法被废弃了。如果找不到__setslice__(),或者对于扩展的切片形式self[i:j:k],则创建一个切片对象并传递给__setitem__(),而不是调用__setslice__()

object.__delslice__(self, i, j)

调用它以实现对self[i:j]的删除。ij的注意事项与__getslice__()相同。该方法已经被废弃了。如果找不到__delslice__(),或者对于扩展的切片形式self[i:j:k],则创建一个切片对象并传递给__delitem__(),而不是调用__delslice__()

注意这些方法只有在使用具有单个冒号的单个切片且切片方法可用时才调用。对于调用扩展切片符号的切片操作,或者切片方法不存在时,则以一个切片对象作为参数调用__getitem__(), __setitem__()__delitem__()

下面的实例演示如何使得你的程序或模块与早期版本的Python兼容(假设__getitem__(), __setitem__()__delitem__()方法支持切片对象为参数):

class MyClass:
    ...
    def __getitem__(self, index):
        ...
    def __setitem__(self, index, value):
        ...
    def __delitem__(self, index):
        ...

    if sys.version_info < (2, 0):
        # They won't be defined if version is at least 2.0 final

        def __getslice__(self, i, j):
            return self[max(0, i):max(0, j):]
        def __setslice__(self, i, j, seq):
            self[max(0, i):max(0, j):] = seq
        def __delslice__(self, i, j):
            del self[max(0, i):max(0, j):]
    ...

注意对max()的调用;它们是必要的因为在调用__*slice__()方法前对负索引的处理。当使用负索引时,__*item__()方法收到的参数与提供的参数相同,但是__*slice__()方法得到的是索引值经过“转换后”的形式。对于每一个负索引值,在调用该方法前会加上序列的长度(结果可能仍然是负索引);这是内建序列类型对负索引通常的处理方式,期望__*item__()方法也这么做。然而,因为它们已经这么做了,负索引不可能传进去;它们必须被限制在序列的边界在传递给__*item__()方法之前。顺便调用max(0, i)可以返回合适的值。

3.4.8. 模仿数值类型

The following methods can be defined to emulate numeric objects. Methods corresponding to operations that are not supported by the particular kind of number implemented (e.g., bitwise operations for non-integral numbers) should be left undefined.

object.__add__(self, other)
object.__sub__(self, other)
object.__mul__(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)

These methods are called to implement the binary arithmetic operations (+, -, *, //, %, divmod(), pow(), **, <<, >>, &, ^, |). For instance, to evaluate the expression x + y, where x is an instance of a class that has an __add__() method, x.__add__(y) is called. The __divmod__() method should be the equivalent to using __floordiv__() and __mod__(); it should not be related to __truediv__() (described below). Note that __pow__() should be defined to accept an optional third argument if the ternary version of the built-in pow() function is to be supported.

If one of those methods does not support the operation with the supplied arguments, it should return NotImplemented.

object.__div__(self, other)
object.__truediv__(self, other)

The division operator (/) is implemented by these methods. The __truediv__() method is used when __future__.division is in effect, otherwise __div__() is used. If only one of these two methods is defined, the object will not support division in the alternate context; TypeError will be raised instead.

object.__radd__(self, other)
object.__rsub__(self, other)
object.__rmul__(self, other)
object.__rdiv__(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)

These methods are called to implement the binary arithmetic operations (+, -, *, /, %, divmod(), pow(), **, <<, >>, &, ^, |) with reflected (swapped) operands. These functions are only called if the left operand does not support the corresponding operation and the operands are of different types. [2] For instance, to evaluate the expression x - y, where y is an instance of a class that has an __rsub__() method, y.__rsub__(x) is called if x.__sub__(y) returns NotImplemented.

Note that ternary pow() will not try calling __rpow__() (the coercion rules would become too complicated).

Note

如果右操作数类型是左操作数的一个子类且该子类提供相应操作的映射方法,则在调用左操作数的非映射方法前将调用该方法。This behavior allows subclasses to override their ancestors’ operations.

object.__iadd__(self, other)
object.__isub__(self, other)
object.__imul__(self, other)
object.__idiv__(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)

These methods are called to implement the augmented arithmetic assignments (+=, -=, *=, /=, //=, %=, **=, <<=, >>=, &=, ^=, |=). These methods should attempt to do the operation in-place (modifying self) and return the result (which could be, but does not have to be, self). If a specific method is not defined, the augmented assignment falls back to the normal methods. For instance, to execute the statement x += y, where x is an instance of a class that has an __iadd__() method, x.__iadd__(y) is called. If x is an instance of a class that does not define a __iadd__() method, x.__add__(y) and y.__radd__(x) are considered, as with the evaluation of x + y.

object.__neg__(self)
object.__pos__(self)
object.__abs__(self)
object.__invert__(self)

Called to implement the unary arithmetic operations (-, +, abs() and ~).

object.__complex__(self)
object.__int__(self)
object.__long__(self)
object.__float__(self)

Called to implement the built-in functions complex(), int(), long(), and float(). Should return a value of the appropriate type.

object.__oct__(self)
object.__hex__(self)

Called to implement the built-in functions oct() and hex(). Should return a string value.

object.__index__(self)

Called to implement operator.index(). Also called whenever Python needs an integer object (such as in slicing). Must return an integer (int or long).

New in version 2.5.

object.__coerce__(self, other)

Called to implement “mixed-mode” numeric arithmetic. Should either return a 2-tuple containing self and other converted to a common numeric type, or None if conversion is impossible. When the common type would be the type of other, it is sufficient to return None, since the interpreter will also ask the other object to attempt a coercion (but sometimes, if the implementation of the other type cannot be changed, it is useful to do the conversion to the other type here). A return value of NotImplemented is equivalent to returning None.

3.4.9. 隐式转换规则

这一节用于记录隐式转换的规则。随着语言的逐步发展,隐式转换的规则已经变得很难精确地记录下来;documenting what one version of one particular implementation does is undesirable. Instead, here are some informal guidelines regarding coercion. 在Python 3中,隐式转换将不再支持。

  • If the left operand of a % operator is a string or Unicode object, no coercion takes place and the string formatting operation is invoked instead.

  • It is no longer recommended to define a coercion operation. Mixed-mode operations on types that don’t define coercion pass the original arguments to the operation.

  • New-style classes (those derived from object) never invoke the __coerce__() method in response to a binary operator; the only time __coerce__() is invoked is when the built-in function coerce() is called.

  • For most intents and purposes, an operator that returns NotImplemented is treated the same as one that is not implemented at all.

  • Below, __op__() and __rop__() are used to signify the generic method names corresponding to an operator; __iop__() is used for the corresponding in-place operator. For example, for the operator ‘+‘, __add__() and __radd__() are used for the left and right variant of the binary operator, and __iadd__() for the in-place variant.

  • For objects x and y, first x.__op__(y) is tried. If this is not implemented or returns NotImplemented, y.__rop__(x) is tried. If this is also not implemented or returns NotImplemented, a TypeError exception is raised. But see the following exception:

  • Exception to the previous item: if the left operand is an instance of a built-in type or a new-style class, and the right operand is an instance of a proper subclass of that type or class and overrides the base’s __rop__() method, the right operand’s __rop__() method is tried before the left operand’s __op__() method.

    This is done so that a subclass can completely override binary operators. Otherwise, the left operand’s __op__() method would always accept the right operand: when an instance of a given class is expected, an instance of a subclass of that class is always acceptable.

  • When either operand type defines a coercion, this coercion is called before that type’s __op__() or __rop__() method is called, but no sooner. If the coercion returns an object of a different type for the operand whose coercion is invoked, part of the process is redone using the new object.

  • When an in-place operator (like ‘+=‘) is used, if the left operand implements __iop__(), it is invoked without any coercion. When the operation falls back to __op__() and/or __rop__(), the normal coercion rules apply.

  • In x + y, if x is a sequence that implements sequence concatenation, sequence concatenation is invoked.

  • In x * y, if one operand is a sequence that implements sequence repetition, and the other is an integer (int or long), sequence repetition is invoked.

  • Rich comparisons (implemented by methods __eq__() and so on) never use coercion. Three-way comparison (implemented by __cmp__()) does use coercion under the same conditions as other binary operations use it.

  • In the current implementation, the built-in numeric types int, long, float, and complex do not use coercion. All these types implement a __coerce__() method, for use by the built-in coerce() function.

    Changed in version 2.7.

3.4.10. With语句上下文管理器

New in version 2.5.

A context manager is an object that defines the runtime context to be established when executing a with statement. The context manager handles the entry into, and the exit from, the desired runtime context for the execution of the block of code. Context managers are normally invoked using the with statement (described in section The with statement), but can also be used by directly invoking their methods.

Typical uses of context managers include saving and restoring various kinds of global state, locking and unlocking resources, closing opened files, etc.

For more information on context managers, see Context Manager Types.

object.__enter__(self)

进入与该对象相关的运行时刻上下文。如果存在的话,with语句将绑定该方法的返回值到该语句的as子句中指定的目标。

object.__exit__(self, exc_type, exc_value, traceback)

退出与该对象相关的运行时刻上下文。参数描述导致该上下文即将退出的异常。如果该上下文退出时没有异常,三个参数都将为None

如果提供了一个异常,但该方法期望压制该异常(例如,防止它扩散),它应该返回一个真值。否则,该异常将在从该函数退出时被正常处理。

注意__exit__()方法不应该重新抛出传递进去的异常;这是调用者的责任。

另请参阅

PEP 0343 - “with”语句
Python with语句的说明、背景和示例。

3.4.11. Special method lookup for old-style classes

对于旧式类,特殊方法的查找始终与其它方法和属性的查找方式完全相同。无论方法的查找是显式的x.__getitem__(i)还是隐式的x[i]

该行为意味着特殊的方法对于同一个旧式类的不同实例展现不同的行为,如果特殊的属性设置不同:

>>> class C:
...     pass
...
>>> c1 = C()
>>> c2 = C()
>>> c1.__len__ = lambda: 5
>>> c2.__len__ = lambda: 9
>>> len(c1)
5
>>> len(c2)
9

3.4.12. Special method lookup for new-style classes

对于新式类,特殊方法的隐式调用只有它在对象的类型上定义而不是对象实例的字典中定义时才保证正确地工作。该行为是为什么下面的代码引起一个异常的原因(与旧式类的相同例子不同):

>>> class C(object):
...     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__()机制给解释器内部提供重要的速度优化空间,代价是特殊方法的处理缺乏一些灵活性(特殊方法必须在类对象自身上设置,这样解释器调用能够具有一致性)。

脚注

[1]在某些情况下确实可以改变一个对象的类型,在可控特定的条件下。然而这通常不是一个好主意,因为如果处理不正确它可能导致某些非常奇怪的行为。
[2]对于类型相同的操作数,Python假设如果非反射方法(例如__add__())失败则不支持该操作,这是为什么不调用反射函数的原因。