On this page
3. Data model
3.1. 对象,值和类型
对象是 Python 的数据抽象。 Python 程序中的所有数据都由对象或对象之间的关系表示。 (在某种意义上,并且按照冯·诺依曼的“存储程序计算机”模型,代码也由对象表示.)
每个对象都有一个标识,一个类型和一个值。创建对象后,其“身份”就永远不会改变;您可能会认为它是对象在内存中的地址。 'is'运算符比较两个对象的身份; id()函数返回一个表示其身份的整数(当前实现为其地址)。对象的* type 也不可更改。 [1]对象的类型确定该对象支持的操作(例如,“它是否有长度?”),并且还定义了该类型对象的可能值。 type()函数返回对象的类型(对象本身)。某些对象的值可以更改。其值可以更改的对象被称为 mutable ;创建后其值不可更改的对象称为 immutable *。 (当更改可变对象的值时,包含对可变对象的引用的不可变容器对象的值可以更改;但是该容器仍被认为是不可变的,因为它所包含的对象的集合无法更改.因此,不可变性并不是严格意义上的与具有不变的值一样,它更加微妙.)对象的可变性由其类型决定;例如,数字,字符串和 Tuples 是不可变的,而字典和列表则是可变的。
从不显式销毁对象。但是,当它们变得不可访问时,它们可能会被垃圾回收。允许某个实现推迟或完全取消垃圾回收-只要没有收集到仍可到达的对象,垃圾回收的实现方式就取决于实现质量。
CPython 实现细节: CPython 当前使用带有循环计数垃圾的(可选)延迟检测的引用计数方案,该方案会在无法访问时立即收集大多数对象,但不能保证收集包含循环引用的垃圾。有关控制循环垃圾收集的信息,请参见gc模块的文档。其他实现的行为有所不同,CPython 可能会发生变化。当对象变得不可访问时,不要依赖它们的即时完成(例如:始终关闭文件)。
请注意,使用实现的跟踪或调试Function可能会使通常可以收集的对象保持活动状态。另请注意,使用'try…except'语句捕获异常可能会使对象保持活动状态。
一些对象包含对“外部”资源的引用,例如打开的文件或窗口。可以理解,当对象被垃圾回收时,这些资源将被释放,但是由于不能保证垃圾回收的发生,因此此类对象还提供了一种释放外部资源的显式方式,通常是close()
方法。强烈建议使用程序显式关闭此类对象。 'try…finally'语句提供了一种方便的方法。
一些对象包含对其他对象的引用。这些被称为容器。容器的示例是 Tuples,列表和字典。引用是容器值的一部分。在大多数情况下,当我们谈论容器的值时,我们暗含的是值,而不是所包含对象的标识。但是,当我们谈论容器的可变性时,仅隐含了直接包含的对象的身份。因此,如果不可变容器(如 Tuples)包含对可变对象的引用,则当该可变对象更改时,其值也会更改。
类型影响对象行为的几乎所有方面。甚至对象标识的重要性在某种意义上也受到影响:对于不可变类型,计算新值的操作实际上可能返回对具有相同类型和值的任何现有对象的引用,而对于可变对象,则不允许这样做。例如,根据实现的不同,在a = 1; b = 1
,a
和b
之后可能会或可能不会使用值 1 引用相同的对象,但是在c = []; d = []
之后,c
和d
被保证引用了两个不同的,唯一的,新创建的空列表。 (请注意c = d = []
将相同的对象分配给c
和d
.)
3.2. 标准类型层次结构
以下是 Python 内置的类型的列表。扩展模块(使用 C,Java 或其他语言编写,取决于实现)可以定义其他类型。Future 的 Python 版本可能会将类型添加到类型层次结构中(例如,有理数,有效存储的整数数组等)。
下面的某些类型描述包含一个列出“特殊属性”的段落。这些是提供对实现的访问的属性,并不旨在用于一般用途。他们的定义将来可能会改变。
None
- 此类型具有单个值。有一个具有此值的对象。pass内置名称
None
访问此对象。它用于表示在许多情况下不存在值,例如,它是从未显式返回任何内容的函数中返回的。其真实值是错误的。
- 此类型具有单个值。有一个具有此值的对象。pass内置名称
NotImplemented
- 此类型具有单个值。有一个具有此值的对象。pass内置名称
NotImplemented
访问此对象。如果数字方法和丰富比较方法未实现所提供操作数的操作,则可能返回此值。 (然后,解释程序将根据操作员try执行反射操作或其他回退.)其真实值是 true。
- 此类型具有单个值。有一个具有此值的对象。pass内置名称
Ellipsis
- 此类型具有单个值。有一个具有此值的对象。pass内置名称
Ellipsis
访问此对象。它用于指示切片中...
语法的存在。它的真实价值是真实的。
- 此类型具有单个值。有一个具有此值的对象。pass内置名称
-
- 它们由数字 Literals 创建,并由算术运算符和算术内置函数作为结果返回。数字对象是不可变的。一旦 Creating 了价值,就永远不会改变。 Python 数字当然与 math 数字密切相关,但受到计算机中数字表示形式的限制。
Python 区分整数,浮点数和复数:
-
- 这些代表整数 math 集合(正数和负数)中的元素。
整数有三种类型:
Plain integers
- These represent numbers in the range \-2147483648 through 2147483647\. \(The range may be larger on machines with a larger natural word size, but not smaller\.\) When the result of an operation would fall outside this range, the result is normally returned as a long integer \(in some cases, the exception [OverflowError](library-exceptions.html#exceptions.OverflowError) is raised instead\)\. For the purpose of shift and mask operations, integers are assumed to have a binary, 2's complement notation using 32 or more bits, and hiding no bits from the user \(i\.e\., all 4294967296 different bit patterns correspond to different values\)\.
- Long integers
- These represent numbers in an unlimited range, subject to available \(virtual\) memory only\. For the purpose of shift and mask operations, a binary representation is assumed, and negative numbers are represented in a variant of 2's complement which gives the illusion of an infinite string of sign bits extending to the left\.
- Booleans
- These represent the truth values False and True\. The two objects representing the values `False` and `True` are the only Boolean objects\. The Boolean type is a subtype of plain integers, and Boolean values behave like the values 0 and 1, respectively, in almost all contexts, the exception being that when converted to a string, the strings `"False"` or `"True"` are returned, respectively\.
整数表示法则旨在对包含负整数的移位和掩码运算提供最有意义的解释,而在普通整数域和长整数域之间切换时,惊喜最小。如果任何操作在纯整数域中产生结果,则将在长整数域中或使用混合操作数时产生相同的结果。域之间的切换对程序员是透明的。
-
- 这些代表机器级别的双精度浮点数。您只能接受底层计算机体系结构(以及 C 或 Java 实现)的接受范围和溢出处理。 Python 不支持单精度浮点数;节省处理器和内存使用量(通常是使用它们的原因)与在 Python 中使用对象的开销相形见,,因此没有理由使该语言复杂化为两种浮点数。
-
- 这些将复数表示为Pair机器级双精度浮点数。浮点数的注意事项相同。可以pass只读属性
z.real
和z.imag
检索复数z
的实部和虚部。
- 这些将复数表示为Pair机器级双精度浮点数。浮点数的注意事项相同。可以pass只读属性
Sequences
- 这些代表由非负数索引的有限有序集。内置函数len()返回序列的项数。当序列的长度为* n 时,索引集包含数字 0、1,…, n * -1.序列* a 的项目 i *由
a[i]
选择。
- 这些代表由非负数索引的有限有序集。内置函数len()返回序列的项数。当序列的长度为* n 时,索引集包含数字 0、1,…, n * -1.序列* a 的项目 i *由
序列还支持切片:a[i:j]
选择索引为* k 的所有项目,使得 i * <=
* k * <
* j *。当用作表达式时,切片是相同类型的序列。这意味着对索引集进行了重新编号,使其从 0 开始。
一些序列还支持带有第三个“ step”参数的“扩展切片”:a[i:j:k]
选择索引为* x 的 a 的所有项,其中x = i + n*k
, n * >=
0
和* i * <=
* x * <
* j *。
序列根据其可变性进行区分:
Immutable sequences
- 不变序列类型的对象一旦创建就无法更改。 (如果对象包含对其他对象的引用,则这些其他对象可能是可变的,并且可能会更改;但是,不可变对象直接引用的对象的集合不能更改.)
以下类型是不可变序列:
Strings
- The items of a string are characters\. There is no separate character type; a character is represented by a string of one item\. Characters represent \(at least\) 8\-bit bytes\. The built\-in functions [chr\(\)](library-functions.html#chr) and [ord\(\)](library-functions.html#ord) convert between characters and nonnegative integers representing the byte values\. Bytes with the values 0–127 usually represent the corresponding ASCII values, but the interpretation of values is up to the program\. The string data type is also used to represent arrays of bytes, e\.g\., to hold data read from a file\.
(在本机字符集不是 ASCII 的系统上,如果函数chr()和ord()实现了 ASCII 和 EBCDIC 之间的 Map,并且字符串比较保留了 ASCIISequences,则字符串可以在其内部表示中使用 EBCDIC。或者也许有人可以提出更好的规则?)
- Unicode
- The items of a Unicode object are Unicode code units\. A Unicode code unit is represented by a Unicode object of one item and can hold either a 16\-bit or 32\-bit value representing a Unicode ordinal \(the maximum value for the ordinal is given in `sys.maxunicode` , and depends on how Python is configured at compile time\)\. Surrogate pairs may be present in the Unicode object, and will be reported as two separate items\. The built\-in functions [unichr\(\)](library-functions.html#unichr) and [ord\(\)](library-functions.html#ord) convert between code units and nonnegative integers representing the Unicode ordinals as defined in the Unicode Standard 3\.0\. Conversion from and to other encodings are possible through the Unicode method `encode()` and the built\-in function [unicode\(\)](library-functions.html#unicode)\.
- Tuples
- The items of a tuple are arbitrary Python objects\. Tuples of two or more items are formed by comma\-separated lists of expressions\. A tuple of one item \(a 'singleton'\) can be formed by affixing a comma to an expression \(an expression by itself does not create a tuple, since parentheses must be usable for grouping of expressions\)\. An empty tuple can be formed by an empty pair of parentheses\.
Mutable sequences
- 创建可变序列后,可以对其进行更改。订阅和切片符号可以用作分配和del(删除)语句的目标。
当前有两种固有的可变序列类型:
Lists
- The items of a list are arbitrary Python objects\. Lists are formed by placing a comma\-separated list of expressions in square brackets\. \(Note that there are no special cases needed to form lists of length 0 or 1\.\)
- Byte Arrays
- A bytearray object is a mutable array\. They are created by the built\-in [bytearray\(\)](library-functions.html#bytearray) constructor\. Aside from being mutable \(and hence unhashable\), byte arrays otherwise provide the same interface and functionality as immutable bytes objects\.
扩展模块array提供了可变序列类型的其他示例。
Set types
- 这些代表无序,有限的唯一不变对象集。因此,它们不能由任何下标索引。但是,可以对其进行迭代,并且内置函数len()返回集合中的项目数。集的常见用途是快速成员资格测试,从序列中删除重复项以及计算 math 运算(例如交集,并集,差和对称差)。
对于集合元素,相同的不变性规则适用于字典键。请注意,数字类型遵循数字比较的一般规则:如果两个数字比较相等(例如1
和1.0
),则集合中只能包含其中一个。
当前有两种内部集类型:
Sets
- 这些代表可变的集合。它们是由内置的set()构造函数创建的,之后可以pass多种方法(例如
add()
)进行修改。
- 这些代表可变的集合。它们是由内置的set()构造函数创建的,之后可以pass多种方法(例如
Frozen sets
- 这些代表一个不变的集合。它们由内置的frozenset()构造函数创建。由于冻结集是不可变的且是hashable,因此它可以再次用作另一个集的元素或用作字典键。
Mappings
当前只有一种内部 Map 类型:
Dictionaries
- 这些代表由几乎任意值索引的有限对象集。唯一不可接受作为键的值类型是包含列表或字典或其他可变类型的值,这些值或值是按值而不是对象标识进行比较的,原因是字典的有效实现需要键的哈希值保持不变。用于键的数字类型遵循数字比较的一般规则:如果两个数字比较相等(例如
1
和1.0
),则可以互换使用它们来索引相同的字典条目。
- 这些代表由几乎任意值索引的有限对象集。唯一不可接受作为键的值类型是包含列表或字典或其他可变类型的值,这些值或值是按值而不是对象标识进行比较的,原因是字典的有效实现需要键的哈希值保持不变。用于键的数字类型遵循数字比较的一般规则:如果两个数字比较相等(例如
字典是可变的;可以使用{...}
表示法创建它们(请参见Dictionary displays部分)。
扩展模块dbm,gdbm和bsddb提供了 Map 类型的其他示例。
Callable types
- 这些是可以应用函数调用操作的类型(请参见Calls):
User-defined functions
- 用户定义的Function对象由Function定义创建(请参见Function definitions)。应该使用包含与函数的形式参数列表相同数量的项的参数列表来调用它。
Special attributes:
Attribute | Meaning | |
---|---|---|
__doc__ func_doc |
该函数的文档字符串,或None (如果不可用)。 |
Writable |
name func_name |
函数名称 | Writable |
__module__ |
函数定义所在的模块的名称,如果不可用,则返回None 。 |
Writable |
__defaults__ func_defaults |
一个 Tuples,其中包含具有默认值的那些参数的默认参数值;如果没有参数具有默认值,则为None 。 |
Writable |
__code__ func_code |
表示已编译函数主体的代码对象。 | Writable |
__globals__ func_globals |
对字典的引用,该字典包含函数的全局变量-定义函数的模块的全局命名空间。 | Read-only |
dict func_dict |
支持任意Function属性的名称空间。 | Writable |
__closure__ func_closure |
None 或包含该函数的自由变量的绑定的单元格 Tuples。 |
Read-only |
标记为“可写”的大多数属性都会检查分配值的类型。
在版本 2.4 中更改:func_name
现在可写。
在 2.6 版中进行了更改:引入了双下划线属性__closure__
,__code__
,__defaults__
和__globals__
作为相应func_*
属性的别名,以便与 Python 3 向前兼容。
函数对象还支持获取和设置任意属性,这些属性可以用于例如将元数据附加到函数。常规属性点符号用于获取和设置此类属性。 请注意,当前实现仅支持用户定义函数上的函数属性。将来可能会支持内置函数的函数属性.
可以从其代码对象中检索有关函数定义的其他信息。请参阅下面的内部类型说明。
User-defined methods
- 用户定义的方法对象将类,类实例(或
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__
。
方法还支持访问(但不设置)基础函数对象上的任意函数属性。
如果某个类的属性是用户定义的函数对象,未绑定的用户定义的方法对象或类的方法对象,则在获取类的属性时(可能pass该类的实例)可以创建用户定义的方法对象。当该属性是用户定义的方法对象时,仅当要从中检索该属性的类与原始方法对象中存储的类相同或派生出类时,才创建新的方法对象;否则,将按原样使用原始方法对象。
pass从类中检索用户定义的函数对象创建用户定义的方法对象时,其im_self
属性为None
,并且该方法对象被认为是未绑定的。当pass某个类的实例之一从类中检索用户定义的函数对象而创建一个对象时,其im_self
属性是该实例,并且该方法对象称为绑定对象。无论哪种情况,新方法的im_class
属性都是从其进行检索的类,而其im_func
属性是原始函数对象。
当pass从类或实例中检索另一个方法对象创建用户定义的方法对象时,其行为与Function对象相同,只是新实例的im_func
属性不是原始方法对象,而是其im_func
属性。 。
pass从类或实例中检索类方法对象创建用户定义的方法对象时,其im_self
属性是类本身,而其im_func
属性是该类方法下的函数对象。
调用未绑定的用户定义的方法对象时,将调用基础函数(im_func
),并具有以下限制:第一个参数必须是适当类(im_class
)或其派生类的实例。
调用绑定的用户定义的方法对象时,将调用基础函数(im_func
),并将类实例(im_self
)插入参数列表的前面。例如,当C
是包含函数f()
的定义的类,并且x
是C
的实例时,调用x.f(1)
等效于调用C.f(x, 1)
。
当从类方法对象派生用户定义的方法对象时,存储在im_self
中的“类实例”实际上将是类本身,因此调用x.f(1)
或C.f(1)
等效于调用f(C,1)
,其中f
是基础函数。
请注意,每次从类或实例检索属性时,都会发生从函数对象到(未绑定或绑定)方法对象的转换。在某些情况下,卓有成效的优化是将属性分配给局部变量并调用该局部变量。还要注意,这种转换仅发生在用户定义的函数上。其他可调用对象(以及所有不可调用对象)无需进行转换即可检索。同样重要的是要注意,作为类实例属性的用户定义函数不会转换为绑定方法。 仅发生在函数是类的属性时。
Generator functions
Built-in functions
- 内置函数对象是 C 函数的包装器。内置函数的示例是len()和math.sin()(math是标准的内置模块)。参数的数量和类型由 C 函数确定。特殊的只读属性:
__doc__
是函数的文档字符串,或None
(如果不可用); name是函数的名称;__self__
设置为None
(但请参见下一项);__module__
是定义Function的模块的名称,或None
(如果不可用)。
- 内置函数对象是 C 函数的包装器。内置函数的示例是len()和math.sin()(math是标准的内置模块)。参数的数量和类型由 C 函数确定。特殊的只读属性:
Built-in methods
- 这实际上是内置函数的另一种伪装,这次包含一个作为隐式额外参数传递给 C 函数的对象。内置方法的一个示例是
alist.append()
,假设* alist 是列表对象。在这种情况下,特殊的只读属性__self__
被设置为 alist *表示的对象。
- 这实际上是内置函数的另一种伪装,这次包含一个作为隐式额外参数传递给 C 函数的对象。内置方法的一个示例是
Class Types
Classic Classes
Class instances
- 类实例如下所述。仅当类具有call()方法时,类实例才可调用;
x(arguments)
是x.__call__(arguments)
的简写。
- 类实例如下所述。仅当类具有call()方法时,类实例才可调用;
Modules
属性分配会更新模块的名称空间字典,例如m.x = 1
等效于m.__dict__["x"] = 1
。
特殊的只读属性:dict是作为字典对象的模块的命名空间。
CPython 实现细节: 由于 CPython 清除模块词典的方式,即使模块仍具有实时引用,当模块超出范围时,模块词典也会被清除。为避免这种情况,请复制字典或在直接使用其字典时保留模块。
sched 义(可写)属性:__name__
是模块的名称; __doc__
是模块的文档字符串,或None
(如果不可用); __file__
是从中加载模块的文件的路径名(如果它是从文件加载的)。静态链接到解释器的 C 模块不提供__file__
属性。对于从共享库动态加载的扩展模块,它是共享库文件的路径名。
Classes
- 类类型(新样式类)和类对象(旧样式/经典类)通常都是由类定义创建的(请参阅Class definitions)。类具有由字典对象实现的名称空间。类属性引用被翻译成该字典中的查询,例如
C.x
被翻译成C.__dict__["x"]
(尽管特别是对于新式类,有许多钩子允许使用其他方式查找属性)。当在此处找不到属性名称时,将 continue 在 Base Class 中搜索属性。对于旧类,搜索是从深度优先,从左到右,从 Base Class 列表的出现 Sequences 开始。new-style类使用更复杂的 C3 方法解析 Sequences,即使在“钻石”继承结构(其中有多个继承路径返回到共同祖先)的情况下,该行为也能正确运行。新样式类使用的 C3 MRO 的其他详细信息可以在 2.3 版本https://www.python.org/download/releases/2.3/mro/随附的文档中找到。
- 类类型(新样式类)和类对象(旧样式/经典类)通常都是由类定义创建的(请参阅Class definitions)。类具有由字典对象实现的名称空间。类属性引用被翻译成该字典中的查询,例如
当类属性引用(例如C
类)产生用户定义的函数对象或未绑定的用户定义的方法对象(其关联的类是C
或其 Base Class 之一)时,它将转换为未绑定的用户定义im_class
属性为C
的方法对象。当产生类方法对象时,它将转换为绑定的用户定义方法对象,该对象的im_self
属性为C
。当产生静态方法对象时,它将转换为由静态方法对象包装的对象。有关从类检索的属性可能与实际包含在其dict中的属性不同的另一种方式,请参见Implementing Descriptors节(请注意,仅新式类支持 Descriptors)。
类属性分配更新类的字典,而不更新 Base Class 的字典。
可以调用一个类对象(请参见上文)以产生一个类实例(请参见下文)。
特殊属性:name是类名; __module__
是定义类的模块名称; dict是包含类名称空间的字典; bases是一个包含 Base Class 的 Tuples(可能为空或单例),按照 Base Class 在 Base Class 列表中的出现 Sequences 排列; __doc__
是该类的文档字符串,或者None
(如果未定义)。
Class instances
- pass调用类对象来创建类实例(请参见上文)。一个类实例具有一个实现为字典的名称空间,这是搜索属性引用的第一位。如果在该处找不到属性,并且实例的类具有该名称的属性,则 continue 使用类属性进行搜索。如果发现一个类属性是一个用户定义的函数对象或一个未绑定的用户定义的方法对象,其关联的类是为其启动属性引用的实例的类(称为
C
)或其基础之一,则它转换为绑定的用户定义方法对象,该对象的im_class
属性为C
且im_self
属性为实例。静态方法和类方法对象也将转换,就好像它们是从C
类中检索的一样;请参见上文“类别”下的内容。有关pass其实例检索的类的属性可能与实际存储在该类dict中的对象不同的另一种方式,请参见Implementing Descriptors部分。如果未找到 class 属性,并且对象的类具有getattr()方法,则调用该方法以满足查找。
- pass调用类对象来创建类实例(请参见上文)。一个类实例具有一个实现为字典的名称空间,这是搜索属性引用的第一位。如果在该处找不到属性,并且实例的类具有该名称的属性,则 continue 使用类属性进行搜索。如果发现一个类属性是一个用户定义的函数对象或一个未绑定的用户定义的方法对象,其关联的类是为其启动属性引用的实例的类(称为
属性分配和删除将更新实例的字典,而不会更新类的字典。如果该类具有setattr()或delattr()方法,则将调用此方法,而不是直接更新实例字典。
如果类实例具有使用某些特殊名称的方法,则它们可以 Feign 为数字,序列或 Map。参见特殊方法名称部分。
Files
- 文件对象代表一个打开的文件。文件对象是由内置的open()函数以及套接字对象的os.popen(),os.fdopen()和
makefile()
方法(以及可能由扩展模块提供的其他函数或方法)创建的。将对象sys.stdin
,sys.stdout
和sys.stderr
初始化为与解释器的标准 Importing,输出和错误流相对应的文件对象。有关文件对象的完整文档,请参见File Objects。
- 文件对象代表一个打开的文件。文件对象是由内置的open()函数以及套接字对象的os.popen(),os.fdopen()和
Internal types
- 解释器内部使用的一些类型向用户公开。它们的定义可能会随将来版本的解释器而变化,但是为了完整起见在此提及它们。
Code objects
- 代码对象表示字节编译的可执行 Python 代码或bytecode。代码对象和Function对象之间的区别在于,Function对象包含对函数全局变量(定义该模块的模块)的显式引用,而代码对象则不包含上下文。默认参数值也存储在函数对象中,而不存储在代码对象中(因为它们表示运行时计算出的值)。与函数对象不同,代码对象是不可变的,并且不包含(直接或间接)可变对象的引用。
特殊的只读属性:co_name
给出函数名称; co_argcount
是位置参数(包括具有默认值的参数)的数量; co_nlocals
是函数使用的局部变量的数量(包括参数); co_varnames
是一个包含局部变量名称的 Tuples(以参数名称开头); co_cellvars
是一个 Tuples,其中包含嵌套函数引用的局部变量的名称; co_freevars
是一个包含自由变量名称的 Tuples; co_code
是代表字节码指令序列的字符串; co_consts
是一个 Tuples,包含字节码使用的 Literals; co_names
是一个 Tuples,包含字节码使用的名称; co_filename
是用于编译代码的文件名; co_firstlineno
是函数的第一行号; co_lnotab
是编码从字节码偏移量到行号的 Map 的字符串(有关详细信息,请参见解释器的源代码); co_stacksize
是所需的堆栈大小(包括局部变量); co_flags
是对解释器的许多标志进行编码的整数。
为co_flags
定义了以下标志位:如果函数使用*arguments
语法接受任意数量的位置参数,则设置位0x04
;如果函数使用**keywords
语法接受任意关键字参数,则设置位0x08
;如果函数是生成器,则设置位0x20
。
将来的Function语句(from __future__ import division
)也使用co_flags
中的位来指示是否在启用了特定Function的情况下编译了代码对象:如果Function在启用了 Future 除法的情况下进行编译,则位0x2000
设置;否则,早期版本的 Python 中使用了0x10
和0x1000
位。
co_flags
中的其他位保留供内部使用。
如果代码对象表示函数,则co_consts
中的第一项是函数的文档字符串,或者None
(如果未定义)。
Frame objects
- 框架对象代表执行框架。它们可能发生在回溯对象中(见下文)。
特殊的只读属性:f_back
指向上一个堆栈帧(面向调用方),或者None
(如果这是底部堆栈帧); f_code
是在此框架中执行的代码对象; f_locals
是用于查找局部变量的字典; f_globals
用于全局变量; f_builtins
用于内置(内部)名称; f_restricted
是指示Function是否在受限执行模式下执行的标志; f_lasti
给出精确的指令(这是代码对象的字节码字符串的索引)。
特殊的可写属性:f_trace
(如果不是None
)是在每个源代码行的开头调用的函数(调试器使用该函数); f_exc_type
,f_exc_value
,f_exc_traceback
表示在父帧中引发的最后一个异常,前提是当前帧中曾引发过另一个异常(在所有其他情况下均为None
); f_lineno
是该帧的当前行号-从跟踪函数中写入该行号将跳至给定的行(仅适用于最底部的帧)。调试器可以pass写入 f_lineno 来实现 Jump 命令(也称为 Set Next 语句)。
Traceback objects
- traceback 对象表示异常的堆栈跟踪。发生异常时创建回溯对象。当搜索异常处理程序展开执行堆栈时,在每个展开级别上,都会在当前回溯的前面插入一个回溯对象。Importing 异常处理程序后,堆栈跟踪可用于程序。 (请参见try 语句。)它可以作为
sys.exc_traceback
以及sys.exc_info()
返回的 Tuples 的第三项来访问。后者是首选接口,因为当程序使用多个线程时它可以正常工作。当程序不包含合适的处理程序时,堆栈跟踪将被写入(格式正确)到标准错误流中。如果解释器是交互式的,则它也以sys.last_traceback
的形式提供给用户。
- traceback 对象表示异常的堆栈跟踪。发生异常时创建回溯对象。当搜索异常处理程序展开执行堆栈时,在每个展开级别上,都会在当前回溯的前面插入一个回溯对象。Importing 异常处理程序后,堆栈跟踪可用于程序。 (请参见try 语句。)它可以作为
特殊的只读属性:tb_next
是堆栈跟踪中的下一层(朝向发生异常的帧),或None
(如果没有下一层); tb_frame
指向当前级别的执行框架; tb_lineno
给出发生异常的行号; tb_lasti
表示精确指令。如果异常发生在try语句中,没有匹配的 except 子句或带有 finally 子句,则回溯中的行号和最后一条指令可能与其框架对象的行号不同。
Slice objects
- 当使用“扩展切片语法”时,切片对象用于表示切片。这是一个使用两个冒号的切片,或者是多个以逗号分隔的切片或椭圆,例如
a[i:j:step]
,a[i:j, k:l]
或a[..., i:j]
。它们也由内置的slice()函数创建。
- 当使用“扩展切片语法”时,切片对象用于表示切片。这是一个使用两个冒号的切片,或者是多个以逗号分隔的切片或椭圆,例如
特殊的只读属性:start
是下限; stop
是上限; step
是步长值;如果Ellipsis,则每个为None
。这些属性可以具有任何类型。
切片对象支持一种方法:
slice.
indices
(* self , length )
-此方法采用单个整数参数 length ,并计算有关切片对象(如果应用于 length 项目序列)将描述的扩展切片的信息。它返回三个整数的 Tuples。它们分别是 start 和 stop 索引以及切片的 step *或步幅。丢失或越界索引的处理方式与常规切片一致。
2.3 版的新Function。
静态方法对象
- 静态方法对象提供了一种克服Function对象向上述方法对象的转换的方法。静态方法对象是任何其他对象(通常是用户定义的方法对象)的包装。从类或类实例中检索静态方法对象时,实际返回的对象是包装的对象,无需进行任何进一步的转换。静态方法对象本身不是可调用的,尽管它们通常包装的对象是可调用的。静态方法对象由内置的staticmethod()构造函数创建。
类方法对象
- 类方法对象就像静态方法对象一样,是另一个对象的包装,它更改了从类和类实例检索该对象的方式。上面在“用户定义的方法”下描述了此类检索时类方法对象的行为。类方法对象是由内置的classmethod()构造函数创建的。
3.3. New-style and classic classes
类和实例有两种风格:旧样式(或经典样式)和新样式。
在 Python 2.1 之前,class
的概念与type
的概念无关,而旧式类是唯一可用的样式。对于老式类,语句x.__class__
提供* x *的类,但type(x)
始终为<type 'instance'>
。这反映了一个事实,即所有旧式实例(独立于其类)均使用称为instance
的单个内置类型实现。
在 Python 2.2 中引入了新的类,以统一class
和type
的概念。new-style类只是用户定义的类型,不多也不少。如果* x *是新样式类的实例,则type(x)
通常与x.__class__
相同(尽管不能保证–允许新样式类实例覆盖x.__class__
返回的值)。
引入new-style类的主要动机是提供具有完整元模型的统Pair象模型。它还具有许多实际的好处,例如可以对大多数内置类型进行子类化,或者可以引入“Descriptors”来启用计算属性。
出于兼容性原因,默认情况下,类仍为旧样式。pass将另一个新样式类(即一种类型)指定为父类来创建新样式类,如果不需要其他父类,则可以指定“顶级类型” object。新样式类的行为与旧样式类的行为不同,除了type()返回的内容外,还有许多重要的细节。其中一些更改是新对象模型的基础,例如调用特殊方法的方式。其他是出于兼容性考虑而无法实现的“修复程序”,例如在多重继承的情况下的方法解析 Sequences。
尽管本手册旨在全面介绍 Python 的类机制,但在涉及新样式类的某些领域可能仍然缺少。有关其他信息的来源,请参见https://www.python.org/doc/newstyle/。
Python 3 中删除了旧式类,仅保留了新式类。
3.4. 特殊方法名称
一个类可以pass定义具有特殊名称的方法,来实现由特殊语法调用的某些操作(例如算术运算或下标和切片)。这是 Python 的运算符重载的方法,允许类针对语言运算符定义自己的行为。例如,如果一个类定义了一个名为getitem()的方法,并且x
是该类的实例,则x[i]
大致等效于x.__getitem__(i)
(对于旧样式类)和type(x).__getitem__(x, i)
(对于新样式类)。除非另有说明,否则当未定义适当的方法(通常为AttributeError或TypeError)时,try执行操作会引发异常。
当实现模拟任何内置类型的类时,重要的是,仅在对要建模的对象有意义的程度上实现模拟。例如,某些序列可能适用于单个元素的检索,但是提取切片可能没有意义。 (一个示例是 W3C 的文档对象模型中的NodeList
接口.)
3.4.1. 基本定制
object.
__new__
(* cls * [,* ... *])
典型实现pass使用带有适当参数的super(currentclass, cls).__new__(cls[, ...])
调用超类的new()方法来创建类的新实例,然后在返回之前根据需要修改新创建的实例。
如果new()返回* cls 的实例,则将像__init__(self[, ...])
一样调用新实例的init()方法,其中 self *是新实例,其余参数与传递给new()的参数相同。
如果new()不返回* cls *实例,则将不会调用新实例的init()方法。
new()主要用于允许不可变类型(例如 int,str 或 tuple)的子类自定义实例创建。为了自定义类的创建,通常也将其覆盖在自定义元类中。
object.
__init__
(* self * [,* ... *])
因为new()和init()在构造对象时一起工作(使用new()创建它,用init()对其进行自定义),所以init()不会返回任何非None
的值;这样做将导致在运行时引发TypeError。
object.
__del__
(* self *)
Note
del x
不会直接调用x.__del__()
-前者会将x
的引用计数减一,而后者仅在x
的引用计数达到零时才调用。可能会阻止对象的引用计数变为零的一些常见情况包括:对象之间的循环引用(例如,双向链接列表或具有父和子指针的树数据结构);对捕获异常的函数的堆栈框架上的对象的引用(存储在sys.exc_traceback
中的回溯使堆栈框架保持活动状态);或对在交互式模式下引发未处理异常的堆栈框架上对象的引用(存储在sys.last_traceback
中的回溯使堆栈框架保持活动状态)。第一种情况只能pass明确 break 循环来解决。pass将None
存储在sys.exc_traceback
或sys.last_traceback
中,可以解决后两种情况。启用选项循环检测器(默认情况下处于启用状态)时,将检测为垃圾的循环引用,但只有在不涉及 Python 级别的del()方法的情况下,才能对其进行清理。有关循环检测器如何处理del()方法的更多信息,尤其是garbage
值的说明,请参阅gc模块的文档。
Warning
另请参见-R命令行选项。
object.
__repr__
(* self *)
这通常用于调试,因此重要的是,表示形式必须信息丰富且明确。
object.
__str__
(* self *)
object.
__lt__
(* self , other *)object.
__le__
(* self , other *)object.
__eq__
(* self , other *)object.
__ne__
(* self , other *)object.
__gt__
(* self , other *)object.
__ge__
(* self , other *)- 2.1 版中的新Function。
这些是所谓的“丰富比较”方法,它们优先于下面的cmp()用作比较运算符。运算符和方法名称之间的对应关系如下:x<y
调用x.__lt__(y)
,x<=y
调用x.__le__(y)
,x==y
调用x.__eq__(y)
,x!=y
和x<>y
调用x.__ne__(y)
,x>y
调用x.__gt__(y)
和x>=y
调用x.__ge__(y)
。
如果丰富的比较方法未实现给定参数对的操作,则可能返回单例NotImplemented
。按照惯例,返回False
和True
以进行成功比较。但是,这些方法可以返回任何值,因此,如果在布尔上下文中使用比较运算符(例如,在if
语句的条件下),Python 将在该值上调用bool()以确定结果是 true 还是 false。
比较运算符之间没有隐含的关系。 x==y
的 Truth 并不意味着x!=y
为假。因此,在定义eq()时,还应定义ne(),以便操作员将按预期方式工作。有关创建hashable对象(支持自定义比较操作并可用作字典键)的一些重要说明,请参见hash()上的段落。
这些方法没有交换参数版本(当左参数不支持该操作但右参数支持该操作时使用); lt()和gt()是彼此的反射,le()和ge()是彼此的反射,而eq()和ne()是它们自己的反射。
丰富比较方法的论点永远不会被强迫。
要从单个 root 操作自动生成排序操作,请参见functools.total_ordering()。
object.
__cmp__
(* self , other *)
object.
__rcmp__
(* self , other *)- 在版本 2.1 中更改:不再受支持。
object.
__hash__
(* self *)
def __hash__(self):
return hash((self.name, self.nick, self.color))
如果一个类没有定义cmp()或eq()方法,那么它也不应该定义hash()操作;如果它定义cmp()或eq()而不是hash(),则其实例将无法在哈希集合中使用。如果一个类定义了可变对象并实现了cmp()或eq()方法,则不应实现hash(),因为可哈希收集实现要求对象的哈希值是不可变的(如果对象的哈希值发生更改,它将位于错误的哈希存储桶中)。
用户定义的类默认情况下具有cmp()和hash()方法。使用它们,所有对象比较不相等(除了它们本身),并且x.__hash__()
返回从id(x)
派生的结果。
从父类继承hash()方法但更改cmp()或eq()的含义,以使返回的哈希值不再合适的类(例如,pass切换到基于值的相等性概念,而不是默认的基于身份的相等性)的类可以显式地pass在类定义中设置__hash__ = None
来将自己标记为不可散列。这样做意味着不仅在程序try检索其哈希值时,该类的实例将引发一个适当的TypeError,而且在检查isinstance(obj, collections.Hashable)
时也将它们正确标识为不可哈希(与定义自己的hash()以显式引发TypeError的类不同)。 。
在版本 2.5 中进行了更改:hash()现在也可能返回一个长整数对象;然后,从该对象的哈希中得出 32 位整数。
在 2.6 版中进行了更改:现在可以将hash设置为None,以将类的实例显式标记为不可散列。
object.
__nonzero__
(* self *)
object.
__unicode__
(* self *)- 调用以实现unicode()内置;应该返回一个 Unicode 对象。未定义此方法时,将try进行字符串转换,并使用系统默认编码将字符串转换的结果转换为 Unicode。
3.4.2. 自定义属性访问
可以定义以下方法来自定义类实例的属性访问(使用,分配或删除x.name
)的含义。
object.
__getattr__
(* self , name *)- 当属性查找未在通常位置找到该属性时调用(即,它不是实例属性,也不是在
self
的类树中找到该属性)。name
是属性名称。此方法应返回(计算出的)属性值或引发AttributeError异常。
- 当属性查找未在通常位置找到该属性时调用(即,它不是实例属性,也不是在
请注意,如果pass常规机制找到该属性,则不会调用getattr()。 (这是getattr()和setattr()之间的故意不对称。)这样做既出于效率考虑,又因为getattr()无法访问实例的其他属性。请注意,至少对于实例变量,您可以pass不在实例属性字典中插入任何值(而是将其插入另一个对象中)来伪造总体控制。请参见下面的getattribute()方法,以了解一种实际获得新样式类中的总控制权的方法。
object.
__setattr__
(* self , name , value *)- try分配属性时调用。这被称为而不是常规机制(即,将值存储在实例字典中)。 * name 是属性名称, value *是要为其分配的值。
如果setattr()要分配给实例属性,则不应简单地执行self.name = value
-这将导致对其自身的递归调用。而是应将值插入实例属性的字典中,例如self.__dict__[name] = value
。对于new-style类,应该访问具有相同名称的 Base Class 方法,例如object.__setattr__(self, name, value)
,而不是访问实例字典。
object.
__delattr__
(* self , name *)- 类似于setattr(),但用于属性删除而不是分配。仅当
del obj.name
对对象有意义时,才应实现此目的。
- 类似于setattr(),但用于属性删除而不是分配。仅当
3.4.2.1. new-style类的更多属性访问
以下方法仅适用于new-style类。
object.
__getattribute__
(* self , name *)- 无条件调用以实现类实例的属性访问。如果该类还定义getattr(),则除非getattribute()显式调用它或引发AttributeError,否则不会调用后者。此方法应返回(计算出的)属性值或引发AttributeError异常。为了避免此方法中的无限递归,其实现应始终调用具有相同名称的 Base Class 方法以访问其所需的任何属性,例如
object.__getattribute__(self, name)
。
- 无条件调用以实现类实例的属性访问。如果该类还定义getattr(),则除非getattribute()显式调用它或引发AttributeError,否则不会调用后者。此方法应返回(计算出的)属性值或引发AttributeError异常。为了避免此方法中的无限递归,其实现应始终调用具有相同名称的 Base Class 方法以访问其所需的任何属性,例如
Note
查找特殊方法时,由于pass语言语法或内置函数进行隐式调用的结果,仍可能会绕过此方法。参见new-style类的特殊方法查找。
3.4.2.2. 实现 Descriptors
以下方法仅在包含该方法的类的实例(所谓的* descriptor 类)出现在 owner *类中时(Descriptors 必须位于所有者的类字典或类字典中的其中一个对象中)时适用它的 parent)。在下面的示例中,“属性”是指名称是所有者类'dict中的属性的键的属性。
object.
__get__
(* self , instance , owner *)- 调用以获取所有者类的属性(类属性访问)或该类的实例的属性(实例属性访问)。 * owner 始终是所有者类,而 instance 是pass其访问属性的实例,当pass owner *访问属性时是
None
。此方法应返回(计算出的)属性值或引发AttributeError异常。
- 调用以获取所有者类的属性(类属性访问)或该类的实例的属性(实例属性访问)。 * owner 始终是所有者类,而 instance 是pass其访问属性的实例,当pass owner *访问属性时是
object.
__set__
(* self , instance , value *)- 调用以将所有者类的实例* instance 上的属性设置为新值 value *。
object.
__delete__
(* self , instance *)- 调用以删除所有者类的实例* instance *上的属性。
3.4.2.3. 调用 Descriptors
通常,Descriptors 是具有“绑定行为”的对象属性,其属性访问已被 Descriptors 协议get(),set()和delete()中的方法所覆盖。如果为对象定义了这些方法中的任何一种,则称其为 Descriptors。
属性访问的默认行为是从对象的字典中获取,设置或删除属性。例如,a.x
的查找链从a.__dict__['x']
开始,然后是type(a).__dict__['x']
,并一直到type(a)
的 Base Class(不包括元类)continue。
但是,如果查找到的值是定义 Descriptors 方法之一的对象,则 Python 可能会覆盖默认行为并改为调用 Descriptors 方法。优先级链在何处发生取决于定义了哪些 Descriptors 方法以及如何调用它们。请注意,仅对新样式对象或类(子类object()或type()的子类)调用 Descriptors。
Descriptors 调用的起点是绑定a.x
。参数的组合方式取决于a
:
Direct Call
- 最简单和最不常见的调用是在用户代码直接调用 Descriptors 方法
x.__get__(a)
时。
- 最简单和最不常见的调用是在用户代码直接调用 Descriptors 方法
Instance Binding
- 如果绑定到新式对象实例,则
a.x
转换为调用:type(a).__dict__['x'].__get__(a, type(a))
。
- 如果绑定到新式对象实例,则
Class Binding
- 如果绑定到新样式的类,则
A.x
转换为调用:A.__dict__['x'].__get__(None, A)
。
- 如果绑定到新样式的类,则
Super Binding
- 如果
a
是super的实例,则绑定super(B, obj).m()
在obj.__class__.__mro__
中搜索紧接B
之前的 Base ClassA
,然后pass调用A.__dict__['m'].__get__(obj, obj.__class__)
调用 Descriptors。
- 如果
对于实例绑定,Descriptors 调用的优先级取决于定义了哪些 Descriptors 方法。Descriptors 可以定义get(),set()和delete()的任意组合。如果未定义get(),则访问该属性将返回 Descriptors 对象本身,除非该对象的实例字典中有一个值。如果 Descriptors 定义set()和/或delete(),则它是数据 Descriptors;如果没有定义,则为非数据 Descriptors。通常,数据 Descriptors 同时定义get()和set(),而非数据 Descriptors 仅具有get()方法。定义了set()和get()的数据 Descriptors 始终会覆盖实例字典中的重定义。相反,非数据 Descriptors 可以被实例覆盖。
Python 方法(包括staticmethod()和classmethod())被实现为非数据 Descriptors。因此,实例可以重新定义和覆盖方法。这允许单个实例获取与同一类的其他实例不同的行为。
property()函数被实现为数据 Descriptors。因此,实例无法覆盖属性的行为。
3.4.2.4. slots
默认情况下,新旧类的实例都具有用于属性存储的字典。这浪费了具有很少实例变量的对象的空间。创建大量实例时,空间消耗会变得非常大。
可以pass在新的类定义中定义* __ slots __ *来覆盖默认值。 * __ slots __ 语句采用一系列实例变量,并在每个实例中仅保留足够的空间来容纳每个变量的值。因为未为每个实例创建 __ dict __ *,所以节省了空间。
__slots__
- 可以为该类变量分配一个字符串,可迭代的字符串或具有实例使用的变量名称的字符串序列。如果在新类中定义,则* __ slots __ 为语句的变量保留空间,并防止为每个实例自动创建 __ dict __ 和 __ weakref __ *。
2.2 版中的新Function。
使用* __ slots __ *的注意事项
从没有* __ slots __ 的类继承时,该类的 __ dict __ 属性将始终可访问,因此子类中的 __ slots __ *定义是没有意义的。
如果没有* __ dict __ 变量,则无法为实例分配 __ slots __ *定义中未列出的新变量。try分配给未列出的变量名会引发AttributeError。如果需要动态分配新变量,则在__slots __ *语句中的字符串序列中添加
'__dict__'
。
在版本 2.3 中进行了更改:以前,在 slots __ *语句中添加'__dict__'
将无法分配实例变量名称序列中未特别列出的新属性。
- 对于每个实例,如果没有* __ weakref __ 变量,则定义 __ slots __ *的类将不支持对其实例的弱引用。如果需要弱引用支持,则在__slots __ *语句中的字符串序列中添加
'__weakref__'
。
在版本 2.3 中进行了更改:以前,在 slots __ *语句中添加'__weakref__'
不会启用对弱引用的支持。
-
- __ slots __ 在类级别pass为每个变量名称创建 Descriptors(Implementing Descriptors)实现。结果,类属性不能用于为 __ slots __ *定义的实例变量设置默认值;否则,class 属性将覆盖 Descriptors 分配。
-
- __ slots __ 语句的操作仅限于定义该语句的类。结果,子类将具有 __ dict __ ,除非它们也定义了 __ slots __ (必须仅包含任何 additional *插槽的名称)。
如果一个类定义了也在 Base Class 中定义的插槽,则无法访问由 Base Class 插槽定义的实例变量(除非直接从 Base Class 中获取其 Descriptors)。这使程序的含义不确定。将来可能会添加检查以防止这种情况。
任何非字符串可迭代的对象都可以分配给* __ slots __ *。也可以使用 Map。但是,将来,可能会为每个键对应的值分配特殊含义。
-
- __ class __ 分配仅在两个类具有相同的 __ slots __ *时才有效。
在 2.6 版中进行了更改:以前,如果新类或旧类具有* __ slots __ ,则 __ class __ *分配会引发错误。
3.4.3. 定制类创建
默认情况下,使用type()构造新样式的类。将类定义读入单独的命名空间,并将类名的值绑定到type(name, bases, dict)
的结果。
读取类定义时,如果定义了* __ metaclass __ *,则将调用分配给它的可调用对象,而不是type()。这允许编写监视或更改类创建过程的类或函数:
在创建类之前修改类字典。
返回另一个类的实例–本质上执行工厂函数的角色。
这些步骤必须在元类的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()方法可在调用该类时允许自定义行为,例如并不总是创建一个新实例。
__metaclass__
- 此变量可以是
name
,bases
和dict
的任何可调用接受参数。创建类时,将使用 callable 而不是内置的type()。
- 此变量可以是
2.2 版中的新Function。
适当的元类由以下优先级规则确定:
如果
dict['__metaclass__']
存在,则使用它。否则,如果至少有一个 Base Class,则使用其元类(这将首先查找* __ class __ *属性,如果未找到,则使用其类型)。
否则,如果存在名为__metaclass_的全局变量,则将使用它。
否则,将使用旧的经典元类(types.ClassType)。
元类的潜在用途是无限的。已经探索了一些想法,包括日志记录,接口检查,自动委派,自动属性创建,代理,框架和自动资源锁定/同步。
3.4.4. 自定义实例和子类检查
2.6 版的新Function。
以下方法用于覆盖isinstance()和issubclass()内置函数的默认行为。
特别是,元类abc.ABCMeta实现了这些方法,以便允许将抽象 Base Class(ABC)作为“虚拟 Base Class”添加到任何类或类型(包括内置类型),包括其他 ABC。
class.
__instancecheck__
(* self , instance *)- 如果应将* instance 视为 class *的(直接或间接)实例,则返回 true。如果定义,则调用以实现
isinstance(instance, class)
。
- 如果应将* instance 视为 class *的(直接或间接)实例,则返回 true。如果定义,则调用以实现
class.
__subclasscheck__
(* self , subclass *)- 如果* subclass 应该被视为 class *的(直接或间接)子类,则返回 true。如果定义,则调用以实现
issubclass(subclass, class)
。
- 如果* subclass 应该被视为 class *的(直接或间接)子类,则返回 true。如果定义,则调用以实现
请注意,这些方法是在类的类型(元类)上查找的。它们不能在实际的类中定义为类方法。这与在实例上调用的特殊方法的查找一致,仅在这种情况下,实例本身是一个类。
See also
PEP 3119-介绍抽象 Base Class
包括用于passinstancecheck()和subclasscheck()自定义isinstance()和issubclass()行为的规范,并在向该语言添加抽象 Base Class(请参见abc模块)的情况下激发了该Function。
3.4.5. 模拟可调用对象
object.
__call__
(* self * [,* args ... *])- 当实例被“调用”为函数时调用;如果定义了此方法,则
x(arg1, arg2, ...)
是x.__call__(arg1, arg2, ...)
的简写。
- 当实例被“调用”为函数时调用;如果定义了此方法,则
3.4.6. 模拟容器类型
可以定义以下方法来实现容器对象。容器通常是序列(例如列表或 Tuples)或 Map(例如字典),但也可以表示其他容器。第一组方法用于仿真序列或仿真 Map。区别在于,对于序列,允许的键应为整数* k ,其中0 <= k < N
为整数,其中 N *是序列的长度,或者是切片对象,它们定义项的范围。 (为了向后兼容,还可以定义方法getslice()(请参见下文)以处理简单但不扩展的切片。)还建议 Map 提供方法keys()
,values()
,items()
,has_key()
,get()
,clear()
,setdefault()
,iterkeys()
,itervalues()
,iteritems()
,pop()
,popitem()
,copy()
和update()
的行为类似于 Python 的标准字典对象。 UserDict模块提供DictMixin
类,以帮助从getitem(),setitem(),delitem()和keys()
的基础集中创建这些方法。可变序列应提供append()
,count()
,index()
,extend()
,insert()
,pop()
,remove()
,reverse()
和sort()
的方法,例如 Python 标准列表对象。最后,序列类型应pass定义以下所述的方法add(),radd(),iadd(),mul(),rmul()和imul()来实现加法(表示串联)和乘法(表示重复);他们不应定义coerce()或其他数字运算符。建议 Map 和序列都实现contains()方法,以允许有效使用in
运算符。对于 Map,in
应该等效于has_key()
;对于序列,它应该搜索值。进一步建议 Map 和序列都实现iter()方法,以允许pass容器进行有效的迭代。对于 Map,iter()应该与iterkeys()
相同;对于序列,它应该遍历值。
object.
__len__
(* self *)
CPython 实现细节: 在 CPython 中,长度最大为sys.maxsize。如果长度大于sys.maxsize
,则某些要素(例如len())可能会升高OverflowError。为了防止pass真值测试提高OverflowError
,对象必须定义nonzero()方法。
object.
__getitem__
(* self , key *)- 调用以实现
self[key]
的评估。对于序列类型,可接受的键应为整数和切片对象。请注意,对负索引的特殊解释(如果类希望模拟序列类型)取决于getitem()方法。如果* key 类型不合适,则可能会引发TypeError;如果该值超出了该序列的索引集(在对负值进行任何特殊解释之后),则应加IndexError。对于 Map 类型,如果缺少 key *(不在容器中),则应加KeyError。
- 调用以实现
Note
for循环期望为非法索引引发IndexError,以允许正确检测序列的结尾。
object.
__setitem__
(* self , key , value *)object.
__delitem__
(* self , key *)object.
__missing__
(* self , key *)object.
__iter__
(* self *)- 当容器需要迭代器时,将调用此方法。此方法应返回一个新的迭代器对象,该对象可以遍历容器中的所有对象。对于 Map,它应遍历容器的键,并且还应作为方法
iterkeys()
提供。
- 当容器需要迭代器时,将调用此方法。此方法应返回一个新的迭代器对象,该对象可以遍历容器中的所有对象。对于 Map,它应遍历容器的键,并且还应作为方法
迭代器对象也需要实现此方法;他们必须返回自己。有关迭代器对象的更多信息,请参见Iterator Types。
object.
__reversed__
(* self *)- 内置reversed()调用(如果存在)以实现反向迭代。它应该返回一个新的迭代器对象,该对象以相反的 Sequences 遍历容器中的所有对象。
如果未提供reversed()方法,则内置reversed()将回退到使用序列协议(len()和getitem())。支持序列协议的对象只有在提供比reversed()提供的实现效率更高的实现时,才应提供reversed()。
2.6 版的新Function。
成员资格测试运算符(in和not in)通常实现为序列的迭代。但是,容器对象可以为以下特殊方法提供更有效的实现,这也不要求对象是序列。
object.
__contains__
(* self , item *)- 要求实施成员资格测试操作员。如果* item 在 self *中,则应返回 true,否则返回 false。对于 Map 对象,应考虑 Map 的键而不是值或键-项对。
对于未定义contains()的对象,成员资格测试首先passiter()try迭代,然后passgetitem()try旧的序列迭代协议,请参见语言参考中的本节。
3.4.7. 模拟序列类型的其他方法
可以定义以下可选方法来进一步模拟序列对象。不可变序列方法最多只能定义getslice();可变序列可以定义所有三种方法。
object.
__getslice__
(* self , i , j *)- 从 2.0 版开始不推荐使用:支持将切片对象用作getitem()方法的参数。 (但是,CPython 中的内置类型当前仍实现getslice()。因此,在实现切片时必须在派生类中重写它。)
调用以实现self[i:j]
的评估。返回的对象应该与* self 具有相同的类型。请注意,切片表达式中丢失的 i 或 j *分别被零或sys.maxsize代替。如果在切片中使用负索引,则将序列的长度添加到该索引。如果实例未实现len()方法,则引发AttributeError。不能保证以此方式调整的索引仍然不是负数。大于序列长度的索引不会被修改。如果未找到getslice(),则会创建一个 slice 对象,并将其传递给getitem()。
object.
__setslice__
(* self , i , j , sequence *)- 调用以实现对
self[i:j]
的分配。 * i 和 j *的 Comments 与getslice()相同。
- 调用以实现对
不建议使用此方法。如果未找到setslice(),或者对于self[i:j:k]
形式的扩展切片,将创建一个切片对象,并将其传递给setitem(),而不是调用setslice()。
object.
__delslice__
(* self , i , j *)- 调用以实现
self[i:j]
的删除。 * i 和 j *的 Comments 与getslice()相同。不建议使用此方法。如果未找到delslice(),或者对于形式为self[i:j:k]
的扩展切片,将创建一个切片对象,并将其传递给delitem(),而不是调用delslice()。
- 调用以实现
请注意,只有在使用带有单个冒号的单个切片并且 slice 方法可用时,才调用这些方法。对于涉及扩展切片符号或没有切片方法的切片操作,以切片对象作为参数调用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__()
方法获得索引值的“煮熟”形式。对于每个负索引值,在调用方法之前将序列的长度添加到索引中(这可能仍会导致负索引);这是pass内置序列类型对负索引的常规处理,并且__*item__()
方法也有望实现这一点。但是,由于他们应该已经在执行此操作,因此无法传递负索引。在将它们传递给__*item__()
方法之前,必须将它们限制在序列的范围内。方便地调用max(0, i)
返回正确的值。
3.4.8. 模拟数值类型
可以定义以下方法来模拟数字对象。与未实现的特定种类的数字不支持的操作相对应的方法(例如,非整数的按位运算)应保持未定义状态。
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 *)
如果这些方法之一不支持使用提供的参数进行的操作,则应返回NotImplemented
。
object.
__div__
(* self , other *)object.
__truediv__
(* self , other *)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 *)
请注意,三 Tuplespow()不会try调用rpow()(强制性规则会变得过于复杂)。
Note
如果右操作数的类型是左操作数类型的子类,并且该子类为操作提供了反射方法,则将在左操作数的非反射方法之前调用此方法。此行为允许子类覆盖其祖先的操作。
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 *)object.
__neg__
(* self *)object.
__pos__
(* self *)object.
__abs__
(* self *)object.
__invert__
(* self *)- 调用以实现一元算术运算(
-
,+
,abs()和~
)。
- 调用以实现一元算术运算(
object.
__complex__
(* self *)object.
__int__
(* self *)object.
__long__
(* self *)object.
__float__
(* self *)
object.
__index__
(* self *)- 调用以实现operator.index()。每当 Python 需要整数对象时(例如在切片中),也会调用此方法。必须返回一个整数(int 或 long)。
2.5 版的新Function。
object.
__coerce__
(* self , other *)- 调用以实现“混合模式”数字算法。应该返回一个包含* self 和 other *的 2Tuples(转换为普通数字类型),或者返回
None
(如果无法进行转换)。当通用类型是other
的类型时,返回None
就足够了,因为解释器还将要求另一个对象try强制转换(但是有时,如果不能更改其他类型的实现,则对在此转换为其他类型)。NotImplemented
的返回值等效于None
的返回值。
- 调用以实现“混合模式”数字算法。应该返回一个包含* self 和 other *的 2Tuples(转换为普通数字类型),或者返回
3.4.9. 强制规则
本部分用于记录强制性规则。随着语言的 Developing,强制规则变得难以精确记录。记录一个特定实现的一个版本的Function是不可取的。相反,这里有一些有关胁迫的非正式准则。在 Python 3 中,将不支持强制转换。
如果%运算符的左操作数是字符串或 Unicode 对象,则不进行强制转换,而是调用字符串格式设置操作。
不再建议定义强制操作。未定义强制类型的混合模式操作会将原始参数传递给该操作。
new-style类(从object派生的类)从不调用coerce()方法来响应二进制运算符; coerce()唯一的调用时间是在调用内置函数coerce()时。
在大多数情况下,返回
NotImplemented
的运算符都将与未执行的运算符相同。下面,
__op__()
和__rop__()
用来表示与运算符相对应的通用方法名称;__iop__()
用于相应的就地运算符。例如,对于运算符“+
”,add()和radd()用于二进制运算符的左右变体,而iadd()用于就地变体。对于对象* x 和 y *,首先try
x.__op__(y)
。如果未实现或返回NotImplemented
,则tryy.__rop__(x)
。如果也未实现或返回NotImplemented
,则会引发TypeError异常。但请参见以下异常:上一项的 exception:如果左操作数是内置类型或新样式类的实例,而右操作数是该类型或类的适当子类的实例,并且覆盖基数的
__rop__()
方法,则在左操作数的__op__()
方法之前*,先try右操作数的__rop__()
方法。
这样做是为了使子类可以完全覆盖二进制运算符。否则,左操作数的__op__()
方法将始终接受右操作数:当期望给定类的实例时,该类的子类的实例总是可接受的。
当任何一个操作数类型都定义了强制时,将在调用该类型的
__op__()
或__rop__()
方法之前调用此强制,但不会更早。如果强制返回了调用强制的操作数的其他类型的对象,则使用新对象重做部分过程。当使用就地运算符(如“
+=
”)时,如果左操作数实现__iop__()
,则无需任何强制即可调用它。当操作退回到__op__()
和/或__rop__()
时,将应用常规强制规则。在
x + y
中,如果* x *是实现序列串联的序列,则会调用序列串联。丰富的比较(由方法eq()等实现)从不使用强制。三向比较(由cmp()实现)的确在与其他二进制操作相同的条件下使用强制。
在当前实现中,内置数字类型int,long,float和complex不使用强制。所有这些类型都实现coerce()方法,供内置coerce()函数使用。
在 2.7 版中进行了更改:复杂类型不再对混合类型的二进制算术运算进行coerce()方法的隐式调用。
3.4.10. 使用语句上下文 Management 器
2.5 版的新Function。
- context manager *是一个对象,定义执行with语句时要构建的运行时上下文。上下文 Management 器处理执行代码块所需的运行时上下文的入口和 Export。通常使用with语句(在with 语句部分中进行了描述)调用上下文 Management 器,但也可以pass直接调用其方法来使用上下文 Management 器。
上下文 Management 器的典型用法包括保存和还原各种全局状态,锁定和解锁资源,关闭打开的文件等。
有关上下文 Management 器的更多信息,请参见上下文 Management 器类型。
object.
__enter__
(* self *)object.
__exit__
(* self , exc_type , exc_value , traceback *)- 退出与此对象相关的运行时上下文。这些参数描述了导致退出上下文的异常。如果上下文无 exception 地退出,则所有三个参数均为None。
如果提供了异常,并且该方法希望抑制该异常(即,防止其传播),则它应返回一个真值。否则,将在退出此方法后正常处理异常。
请注意,exit()个方法不应引发传入的异常。这是呼叫者的责任。
3.4.11. 老式类的特殊方法查找
对于老式类,总是以与任何其他方法或属性完全相同的方式查找特殊方法。无论是在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. new-style类的特殊方法查找
对于new-style类,只有在对对象的类型(而不是在对象的实例字典中)进行定义的情况下,才能保证对特殊方法的隐式调用可以正常工作。该行为是以下代码引发异常的原因(与旧类的等效示例不同):
>>> 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
以这种方式错误地try调用类的未绑定方法有时被称为“元类混淆”,pass在查找特殊方法时绕过实例可以避免这种情况:
>>> 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()机器为解释器内的速度优化提供了很大的空间,但以牺牲一些特殊方法的处理为代价(特殊方法必须在类对象本身上设置,以便被一致地调用)Interpreter)。
Footnotes