以下部分描述了解释器中内置的标准类型。
主要内置类型有数字、序列、映射、类、实例和异常。
有些多项集类是可变的。 它们用于添加、移除或重排其成员的方法将原地执行,并不返回特定的项,绝对不会返回多项集实例自身而是返回 None
。
有些操作受多种对象类型的支持;特别地,实际上所有对象都可以比较是否相等、检测逻辑值,以及转换为字符串(使用 函数或略有差异的 函数)。 后一个函数是在对象由 函数输出时被隐式地调用的。
任何对象都可以进行逻辑值的检测,以便在 或 作为条件或是作为下文所述布尔运算的操作数来使用。
一个对象在默认情况下均被视为真值,除非当该对象被调用时其所属类定义了 __bool__()
方法且返回 False
或是定义了 __len__()
方法且返回零。 下面基本完整地列出了会被视为假值的内置对象:
参见 ,该方法将删除单个前缀字符串,而不是全部给定集合中的字符。 例如:
-
要移除的二进制序列可以是任意 。 要删除单个前缀字符串,而不是全部给定集合中的字符,请参见 方法。 例如:
此方法的 bytearray 版本 并非 原地操作 —— 它总是产生一个新对象,即便没有做任何改变。
-
要移除的字节值二进制序列可以是任意 。
此方法的 bytearray 版本 并非 原地操作 —— 它总是产生一个新对象,即便没有做任何改变。
以下 bytes 和 bytearray 对象的方法会假定使用兼容 ASCII 的二进制格式,不应当被应用于任意二进制数据。 请注意本小节中所有的 bytearray 方法都 不是 原地执行操作,而是会产生新的对象。
-
返回原序列的副本,其中每个字节将都将被解读为一个 ASCII 字符,并且第一个字节的字符大写而其余的小写。 非 ASCII 字节值将保持原样不变。
此方法的 bytearray 版本 并非 原地操作 —— 它总是产生一个新对象,即便没有做任何改变。
-
返回序列的副本,其中所有的 ASCII 制表符会由一个或多个 ASCII 空格替换,具体取决于当前列位置和给定的制表符宽度。 每 tabsize 个字节设为一个制表位(默认值 8 时设定的制表位在列 0, 8, 16 依次类推)。 要展开序列,当前列位置将被设为零并逐一检查序列中的每个字节。 如果字节为 ASCII 制表符
(b'\t'
),则并在结果中插入一个或多个空格符,直到当前列等于下一个制表位。 (制表符本身不会被复制。) 如果当前字节为 ASCII 换行符 (b'\n'
) 或回车符 (b'\r'
),它会被复制并将当前列重设为零。
任何其他字节会被不加修改地复制并将当前列加一,不论该字节值在被打印时会如何显示:
此方法的 bytearray 版本 并非 原地操作 —— 它总是产生一个新对象,即便没有做任何改变。
-
如果序列中所有字节都是字母类 ASCII 字符或 ASCII 十进制数码并且序列非空则返回 True
,否则返回 False
。 字母类 ASCII 字符就是字节值包含在序列
-
如果序列中所有字节都是字母类 ASCII 字符并且序列不非空则返回 True
,否则返回 False
。 字母类 ASCII 字符就是字节值包含在序列
-
如果序列为空或序列中所有字节都是 ASCII 字节则返回 True
,否则返回 False
。 ASCII 字节的取值范围是 0-0x7F。
-
如果序列中所有字节都是 ASCII 十进制数码并且序列非空则返回 True
,否则返回 False
。 ASCII 十进制数码就是字节值包含在序列 b''
中的字符。
-
如果序列中至少有一个小写的 ASCII 字符并且没有大写的 ASCII 字符则返回 True
,否则返回 False
。
-
制表, 换行, 回车, 垂直制表, 进纸) 中的字符。
-
如果序列为 ASCII 标题大小写形式并且序列非空则返回 True
,否则返回 False
。 请参阅 了解有关“标题大小写”的详细定义。
-
如果序列中至少有一个大写字母 ASCII 字符并且没有小写 ASCII 字符则返回 True
,否则返回 False
。
-
返回原序列的副本,其所有大写 ASCII 字符均转换为对应的小写形式。
此方法的 bytearray 版本 并非 原地操作 —— 它总是产生一个新对象,即便没有做任何改变。
-
返回由原二进制序列中各行组成的列表,在 ASCII 行边界符的位置拆分。 此方法使用 方式来分行。 结果列表中不包含换行符,除非给出了 keepends 且为真值。
不同于 ,当给出了分隔符 sep 时,对于空字符串此方法将返回一个空列表,而末尾的换行不会令结果中增加额外的行:
-
返回原序列的副本,其所有小写 ASCII 字符均转换为对应的大写形式,反之亦反。
bin 总是成立。 大小写转换在 ASCII 中是对称的,即使其对于任意 Unicode 码位来说并不总是成立。
此方法的 bytearray 版本 并非 原地操作 —— 它总是产生一个新对象,即便没有做任何改变。
-
返回原二进制序列的标题版本,其中每个单词以一个大写 ASCII 字符为开头,其余字母为小写。 不区别大小写的字节值将保持原样不变。
该算法使用一种简单的与语言无关的定义,将连续的字母组合视为单词。 该定义在多数情况下都很有效,但它也意味着代表缩写形式与所有格的撇号也会成为单词边界,这可能导致不希望的结果:
可以使用正则表达式来构建针对撇号的特别处理:
此方法的 bytearray 版本 并非 原地操作 —— 它总是产生一个新对象,即便没有做任何改变。
-
返回原序列的副本,其所有小写 ASCII 字符均转换为对应的大写形式。
此方法的 bytearray 版本 并非 原地操作 —— 它总是产生一个新对象,即便没有做任何改变。
-
返回原序列的副本,在左边填充 b'0'
数码使序列长度为 width。 正负值前缀 (b'+'
/ b'-'
) 的处理方式是在正负符号 之后 填充而非在之前。 对于
此方法的 bytearray 版本 并非 原地操作 —— 它总是产生一个新对象,即便没有做任何改变。
printf
风格的字节串格式化
此处介绍的格式化操作具有多种怪异特性,可能导致许多常见错误(例如无法正确显示元组和字典)。 如果要打印的值可能为元组或字典,请将其放入一个元组中。
字节串对象 (bytes
/bytearray
) 具有一种特殊的内置操作:使用 %
(取模) 运算符。 这也被称为字节串的 格式化 或 插值 运算符。 对于
如果 format 要求一个单独参数,则 values 可以为一个非元组对象。 否则的话,values 必须或是是一个包含项数与格式字节串对象中指定的转换符项数相同的元组,或者是一个单独的映射对象(例如元组)。
转换标记符包含两个或更多字符并具有以下组成,且必须遵循此处规定的顺序:
-
'%'
字符,用于标记转换符的起始。
-
映射键(可选),由加圆括号的字符序列组成 (例如 (somename)
)。
-
转换旗标(可选),用于影响某些转换类型的结果。
-
最小字段宽度(可选)。 如果指定为 '*'
(星号),则实际宽度会从 values 元组的下一元素中读取,要转换的对象则为最小字段宽度和可选的精度之后的元素。
-
精度(可选),以在 '.'
(点号) 之后加精度值的形式给出。 如果指定为 '*'
(星号),则实际精度会从 values 元组的下一元素中读取,要转换的对象则为精度之后的元素。
当右边的参数为一个字典(或其他映射类型)时,字节串对象中的格式 必须 包含加圆括号的映射键,对应 '%'
字符之后字典中的每一项。 映射键将从映射中选取要格式化的值。 例如:
在此情况下格式中不能出现 *
标记符(因其需要一个序列类的参数列表)。
|
值的转换将使用“替代形式”(具体定义见下文)。
|
转换将为数字值填充零字符。
|
转换值将靠左对齐(如果同时给出 '0' 转换,则会覆盖后者)。
|
(空格) 符号位转换产生的正数(或空字符串)前将留出一个空格。
|
符号字符 ('+' 或 '-' ) 将显示于转换结果的开头(会覆盖 "空格" 旗标)。
|
可以给出长度修饰符 (h
, l
或 L
),但会被忽略,因为对 Python 来说没有必要 -- 所以 %ld
等价于
|
|
|
|
|
有符号十六进制数(小写)。
|
有符号十六进制数(大写)。
|
浮点指数格式(小写)。
|
浮点指数格式(大写)。
|
|
|
浮点格式。 如果指数小于 -4 或不小于精度则使用小写指数格式,否则使用十进制格式。
|
浮点格式。 如果指数小于 -4 或不小于精度则使用大写指数格式,否则使用十进制格式。
|
单个字节(接受整数或单个字节对象)。
|
字节串(任何遵循 或是具有 __bytes__() 的对象)。
|
|
|
|
不转换参数,在结果中输出一个 '%' 字符。
|
-
此替代形式会在第一个数码之前插入标示八进制数的前缀 ('0o'
)。
-
此替代形式会在第一个数码之前插入 '0x'
或 '0X'
前缀(取决于是使用 'x'
还是 'X'
格式)。
-
此替代形式总是会在结果中包含一个小数点,即使其后并没有数码。
小数点后的数码位数由精度决定,默认为 6。
-
此替代形式总是会在结果中包含一个小数点,末尾各位的零不会如其他情况下那样被移除。
小数点前后的有效数码位数由精度决定,默认为 6。
-
如果精度为 N
,输出将截短为 N
个字符。
-
b'%s'
已弃用,但在 3.x 系列中将不会被移除。
-
b'%r'
已弃用,但在 3.x 系列中将不会被移除。
此方法的 bytearray 版本 并非 原地操作 —— 它总是产生一个新对象,即便没有做任何改变。
对象允许 Python 代码访问一个对象的内部数据,只要该对象支持
-
创建一个引用 object 的 。 object 必须支持缓冲区协议。支持缓冲区协议的内置对象有 和 。
有 元素 的概念, 元素 指由原始 object 处理的原子内存单元。对于许多简单的类型,如 和 ,一个元素是一个字节,但其他类型,如 可能有更大的元素。
0,则其长度为 1。 如果 view.ndim = 1
,则其长度等于 view 中元素的数量。 对于更高的维度,其长度等于表示 view 的嵌套列表的长度。 属性可向你给出单个元素所占的字节数。
支持通过切片和索引访问其元素。 一维切片的结果将是一个子视图:
如果 是一个来自于 模块的原生格式说明符,则也支持使用整数或由整数构成的元组进行索引,并返回具有正确类型的单个 元素。 一维内存视图可以使用一个整数或由一个整数构成的元组进行索引。 多维内存视图可以使用由恰好 ndim 个整数构成的元素进行索引,ndim 即其维度。 零维内存视图可以使用空元组进行索引。
这里是一个使用非字节格式的例子:
如果下层对象是可写的,则内存视图支持一维切片赋值。 改变大小则不被允许:
在 3.3 版更改: 一维内存视图现在可以被切片。 带有格式符号 'B', 'b' 或 'c' 的一维内存视图现在是可哈希的。
在 3.5 版更改: 内存视图现在可使用整数元组进行索引。
-
memoryview 与 中的导出器这两者如果形状相同,并且如果当使用 语法解读操作数的相应格式代码时所有对应值都相同,则它们就是等价的。
如果两边的格式字符串都不被 模块所支持,则两对象比较结果总是不相等(即使格式字符串和缓冲区内容相同):
请注意,与浮点数的情况一样,对于内存视图对象来说,v is w
也 并不 意味着 v == w
。
在 3.3 版更改: 之前的版本比较原始内存时会忽略条目的格式与逻辑数组结构。
-
将缓冲区中的数据作为字节串返回。 这相当于在内存视图上调用 构造器。
对于非连续数组,结果等于平面化表示的列表,其中所有元素都转换为字节串。 支持所有格式字符串,不符合 模块语法的那些也包括在内。
顺序会被保留。对于非连续视图,数据会先被转换为 C 形式。 order=None 与 order='C' 是相同的。
-
返回一个字符串对象,其中分别以两个十六进制数码表示缓冲区里的每个字节。
-
将缓冲区内的数据以一个元素列表的形式返回。
-
释放由内存视图对象所公开的底层缓冲区。 许多对象在被视图所获取时都会采取特殊动作(例如, 将会暂时禁止调整大小);因此,调用 release() 可以方便地尽早去除这些限制(并释放任何多余的资源)。
在此方法被调用后,任何对视图的进一步操作将引发 ( 本身除外,它可以被多次调用):
使用 with
语句,可以通过上下文管理协议达到类似的效果:
-
目标格式仅限于 语法中的单一元素原生格式。 其中一种格式必须为字节格式 ('B', 'b' 或 'c')。 结果的字节长度必须与原始长度相同。
在 3.5 版更改: 当转换为字节视图时,源格式将不再受限。
还存在一些可用的只读属性:
-
这是数组在连续表示时将会占用的空间总字节数。 它不一定等于 len(m)
:
-
一个表明内存是否只读的布尔值。
-
一个字符串,包含视图中每个元素的格式(表示为 模块样式)。 内存视图可以从具有任意格式字符串的导出器创建,但某些方法 (例如 ) 仅限于原生的单元素格式。
-
memoryview 中每个元素以字节表示的大小:
-
一个整数,表示内存所代表的多维数组具有多少个维度。
-
一个整数元组,通过 的长度值给出内存所代表的 N 维数组的形状。
-
一个整数元组,通过 的长度给出以字节表示的大小,以便访问数组中每个维度上的每个元素。
-
供 PIL 风格的数组内部使用。 该值仅作为参考信息。
-
一个表明内存是否为 C- 的布尔值。
-
一个表明内存是否为 Fortran 的布尔值。
-
一个表明内存是否为 的布尔值。
set 对象是由具有唯一性的 对象所组成的无序多项集。 常见的用途包括成员检测、从序列中去除重复项以及数学中的集合类计算,例如交集、并集、差集与对称差集等等。 (关于其他容器对象请参看 , 与 等内置类,以及
set。 作为一种无序的多项集,集合并不记录元素位置或插入顺序。 相应地,集合不支持索引、切片或其他序列类的操作。
目前有两种内置集合类型, 和 。 类型是可变的 --- 其内容可以使用 add()
和 remove()
这样的方法来改变。 由于是可变类型,它没有哈希值,且不能被用作字典的键或其他集合的元素。 类型是不可变并且为 ---
其内容在被创建后不能再改变;因此它可以被用作字典的键或其他集合的元素。
除了可以使用 构造器,非空的 set (不是 frozenset) 还可以通过将以逗号分隔的元素列表包含于花括号之内来创建,例如: {'jack', 'sjoerd'}
。
两个类的构造器具有相同的作用方式:
-
返回一个新的 set 或 frozenset 对象,其元素来自于 iterable。 集合的元素必须为 。 要表示由集合对象构成的集合,所有的内层集合必须为 对象。 如果未指定 iterable,则将返回一个新的空集合。
集合可用多种方式来创建:
和 的实例提供以下操作:
-
返回集合 s 中的元素数量(即 s 的基数)。
-
检测 x 是否为 s 中的成员。
-
检测 x 是否非 s 中的成员。
-
如果集合中没有与 other 共有的元素则返回 True
。 当且仅当两个集合的交集为空集合时,两者为不相交集合。
-
检测是否集合中的每个元素都在 other 之中。
-
检测是否 other 中的每个元素都在集合之中。
-
返回一个新集合,其中包含来自原集合以及 others 指定的所有集合中的元素。
-
返回一个新集合,其中包含原集合以及 others 指定的所有集合中共有的元素。
-
返回一个新集合,其中包含原集合中在 others 指定的其他集合中不存在的元素。
-
返回一个新集合,其中的元素或属于原集合或属于 other 指定的其他集合,但不能同时属于两者。
注意, 、 、 、 、 和 方法的非运算符版本可以接受任何可迭代对象作为一个参数。相比之下,基于运算符的对应方法则要求参数为集合对象。这就避开了像 set('abc') & 'cbs'
这样容易出错的结构,而换成了可读性更好的
和 均支持集合与集合的比较。 两个集合当且仅当每个集合中的每个元素均包含于另一个集合之内(即各为对方的子集)时则相等。 一个集合当且仅当其为另一个集合的真子集(即为后者的子集但两者不相等)时则小于另一个集合。 一个集合当且仅当其为另一个集合的真超集(即为后者的超集但两者不相等)时则大于另一个集合。
的实例与 的实例之间基于它们的成员进行比较。 例如
子集与相等比较并不能推广为完全排序函数。 例如,任意两个非空且不相交的集合不相等且互不为对方的子集,因此以下 所有 比较均返回 False
: a<b
, a==b
, or
由于集合仅定义了部分排序(子集关系),因此由集合构成的列表 方法的输出并无定义。
集合的元素,与字典的键类似,必须为 。
混合了 实例与 的二进制位运算将返回与第一个操作数相同的类型。例如:
下表列出了可用于 而不能用于不可变的 实例的操作:
-
更新集合,添加来自 others 中的所有元素。
-
更新集合,只保留其中在所有 others 中也存在的元素。
-
更新集合,移除其中也存在于 others 中的元素。
-
更新集合,只保留存在于集合的一方而非共同存在的元素。
-
将元素 elem 添加到集合中。
-
从集合中移除元素 elem。 如果 elem 不存在于集合中则会引发 。
-
如果元素 elem 存在于集合中则将其移除。
-
从集合中移除并返回任意一个元素。 如果集合为空则会引发 。
-
从集合中移除所有元素。
请注意,非运算符版本的 , , 和 方法将接受任意可迭代对象作为参数。
对象会将 值映射到任意对象。 映射属于可变对象。 目前仅有一种标准映射类型 字典。 (关于其他容器对象请参看 , 与 等内置类,以及 模块。)
字典的键 几乎 可以是任何值。 非 的值,即包含列表、字典或其他可变类型的值(此类对象基于值而非对象标识进行比较)不可用作键。 数字类型用作键时遵循数字比较的一般规则:如果两个数值相等 (例如 1
和 1.0
) 则两者可以被用来索引同一字典条目。
(但是请注意,由于计算机对于浮点数存储的只是近似值,因此将其用作字典键是不明智的。)
-
返回一个新的字典,基于可选的位置参数和可能为空的关键字参数集来初始化。
字典可用多种方式来创建:
如果没有给出位置参数,将创建一个空字典。 如果给出一个位置参数并且其属于映射对象,将创建一个具有与映射对象相同键值对的字典。 否则的话,位置参数必须为一个 对象。 该可迭代对象中的每一项本身必须为一个刚好包含两个元素的可迭代对象。 每一项中的第一个对象将成为新字典的一个键,第二个对象将成为其对应的值。 如果一个键出现一次以上,该键的最后一个值将成为其在新字典中对应的值。
如果给出了关键字参数,则关键字参数及其值会被加入到基于位置参数创建的字典。 如果要加入的键已存在,来自关键字参数的值将替代来自位置参数的值。
像第一个例子那样提供关键字参数的方式只能使用有效的 Python 标识符作为键。 其他方式则可使用任何有效的键。
这些是字典所支持的操作(因而自定义的映射类型也应当支持):
-
返回字典 d 中使用的所有键的列表。
-
返回字典 d 中的项数。
-
返回 d 中以 key 为键的项。 如果映射中不存在 key 则会引发 。
如果字典的子类定义了方法 __missing__()
并且 key 不存在,则 d[key]
操作将调用该方法并附带键 key 作为参数。 d[key]
随后将返回或引发
0
上面的例子显示了 实现的部分代码。 还有另一个不同的
-
将 d[key]
从 d 中移除。 如果映射中不存在 key 则会引发 。
-
返回以字典的键为元素的迭代器。 这是 iter(d.keys())
的快捷方式。
-
移除字典中的所有元素。
-
使用来自 iterable 的键创建一个新字典,并将键值设为 value。
是一个返回新字典的类方法。 value 默认为 None
。 所有值都只引用一个单独的实例,因此让 value 成为一个可变对象例如空列表通常是没有意义的。 要获取不同的值,请改用 。
-
如果 key 存在于字典中则返回 key 的值,否则返回 default。 如果 default 未给出则默认为 None
,因而此方法绝不会引发 。
-
返回由字典项 ((键, 值)
对) 组成的一个新视图。 参见 。
-
返回由字典键组成的一个新视图。 参见 。
-
如果 key 存在于字典中则将其移除并返回其值,否则返回 default。 如果 default 未给出且 key 不存在于字典中,则会引发 。
-
从字典中移除并返回一个 (键, 值)
对。 键值对会按 LIFO 的顺序被返回。
适用于对字典进行消耗性的迭代,这在集合算法中经常被使用。 如果字典为空,调用 将引发 。
在 3.7 版更改: 现在会确保采用 LIFO 顺序。 在之前的版本中, 会返回一个任意的键/值对。
-
返回一个逆序获取字典键的迭代器。 这是 reversed(d.keys())
的快捷方式。
-
使用来自 other 的键/值对更新字典,覆盖原有的键。 返回 None
。
接受另一个字典对象,或者一个包含键/值对(以长度为二的元组或其他可迭代对象表示)的可迭代对象。 如果给出了关键字参数,则会以其所指定的键/值对更新字典:
-
返回由字典值组成的一个新视图。 参见 。
-
合并 d 和 other 中的键和值来创建一个新的字典,两者必须都是字典。当 d 和 other 有相同键时, other 的值优先。
字典会保留插入时的顺序。 请注意对键的更新不会影响顺序。 删除并再次添加的键将被插入到末尾。
在 3.7 版更改: 字典顺序会确保为插入顺序。 此行为是自 3.6 版开始的 CPython 实现细节。
字典和字典视图都是可逆的。
在 3.8 版更改: 字典现在是可逆的。
由 , 和 所返回的对象是 视图对象。 该对象提供字典条目的一个动态视图,这意味着当字典改变时,视图也会相应改变。
字典视图可以被迭代以产生与其对应的数据,并支持成员检测:
-
返回字典中的键、值或项(以 (键, 值)
为元素的元组表示)的迭代器。
键和值是按插入时的顺序进行迭代的。 这样就允许使用 来创建 (值, 键)
对: pairs
在添加或删除字典中的条目期间对视图进行迭代可能引发 或者无法完全迭代所有条目。
在 3.7 版更改: 字典顺序会确保为插入顺序。
-
如果 x 是对应字典中存在的键、值或项(在最后一种情况下 x 应为一个 (键, 值)
元组) 则返回 True
。
-
返回一个逆序获取字典键、值或项的迭代器。 视图将按与插入时相反的顺序进行迭代。
在 3.8 版更改: 字典视图现在是可逆的。
-
返回 对象,封装了字典视图指向的原始字典。
键视图类似于集合,因为其条目不重复且可哈希。 如果所有值都是可哈希的,即 (键, 值)
对也是不重复且可哈希的,那么条目视图也会类似于集合。 (值视图则不被视为类似于集合,因其条目通常都是有重复的。) 对于类似于集合的视图,为抽象基类 所定义的全部操作都是有效的 (例如
一个使用字典视图的示例:
Python 的 语句支持通过上下文管理器所定义的运行时上下文这一概念。 此对象的实现使用了一对专门方法,允许用户自定义类来定义运行时上下文,在语句体被执行前进入该上下文,并在语句执行完毕时退出该上下文:
-
进入运行时上下文并返回此对象或关联到该运行时上下文的其他对象。 此方法的返回值会绑定到使用此上下文管理器的 语句的 as
子句中的标识符。
一个返回其自身的上下文管理器的例子是 。 文件对象会从 __enter__() 返回其自身,以允许 被用作 语句中的上下文表达式。
一个返回关联对象的上下文管理器的例子是 所返回的对象。 此种管理器会将活动的 decimal 上下文设为原始 decimal 上下文的一个副本并返回该副本。 这允许对 语句的语句体中的当前 decimal 上下文进行更改,而不会影响 with
语句以外的代码。
-
退出运行时上下文并返回一个布尔值旗标来表明所发生的任何异常是否应当被屏蔽。 如果在执行 语句的语句体期间发生了异常,则参数会包含异常的类型、值以及回溯信息。 在其他情况下三个参数均为
自此方法返回一个真值将导致 语句屏蔽异常并继续执行紧随在 with
语句之后的语句。 否则异常将在此方法结束执行后继续传播。 在此方法执行期间发生的异常将会取代 with
语句的语句体中发生的任何异常。
传入的异常绝对不应当被显式地重新引发 —— 相反地,此方法应当返回一个假值以表明方法已成功完成并且不希望屏蔽被引发的异常。 这允许上下文管理代码方便地检测
Python 定义了一些上下文管理器来支持简易的线程同步、文件或其他对象的快速关闭,以及更方便地操作活动的十进制算术上下文。 除了实现上下文管理协议以外,不同类型不会被特殊处理。 请参阅 模块查看相关的示例。
请注意,Python/C API 中 Python 对象的类型结构中并没有针对这些方法的专门槽位。 想要定义这些方法的扩展类型必须将它们作为普通的 Python 可访问方法来提供。 与设置运行时上下文的开销相比,单个类字典查找的开销可以忽略不计。
类型注解的类型 --- 、
-
另一个例子是关于 对象的,用到了 ,泛型的两个类型参数分别代表了键类型和值类型。本例中的函数需要一个 dict
,其键的类型为 ,值的类型为 :。
不仅如此,在创建对象的过程中,应用了参数后的泛型还会抹除类型参数:
在泛型上调用 或 会显示应用参数之后的类型:
应用参数后的泛型都实现了一些特殊的只读属性:
-
本属性指向未应用参数之前的泛型类:
-
该属性是延迟计算出来的一个元组(可能为空),包含了 __args__
中的类型变量。
联合对象包含了在多个 上执行 |
(按位或) 运算后的值。 这些类型主要用于 。与 相比,联合类型表达式可以实现更简洁的类型提示语法。
-
union 对象可与其他 union 对象进行比较。详细结果如下:
-
多次组合的结果会平推:
-
在相互比较时,会忽略顺序:
-
但不能使用包含 的 union 对象:
union 对象构成的用户类型可以经由 访问,并可用于 检查。 而不能由类型直接实例化为对象:
为了支持 X | Y
语法,类型对象加入了 __or__()
方法。若是元类已实现了 __or__()
,union 也可以覆盖掉:
解释器支持一些其他种类的对象。 这些对象大都仅支持一两种操作。
模块唯一的特殊操作是属性访问: m.name
,这里 m 为一个模块而 name 访问定义在 m 的符号表中的一个名称。 模块属性可以被赋值。 (请注意 语句严格来说也是对模块对象的一种操作;import
foo
不要求存在一个名为 foo 的模块对象,而是要求存在一个对于名为 foo 的模块的 (永久性) 定义。)
每个模块都有一个特殊属性 。 这是包含模块的符号表的字典。 修改此字典将实际改变模块的符号表,但是无法直接对 赋值 (你可以写 m.__dict__['a'] = 1
,这会将 m.a
定义为
函数对象是通过函数定义创建的。 对函数对象的唯一操作是调用它: func(argument-list)
。
实际上存在两种不同的函数对象:内置函数和用户自定义函数。 两者支持同样的操作(调用函数),但实现方式不同,因此对象类型也不同。
方法是使用属性表示法来调用的函数。 存在两种形式:内置方法(例如列表的 append()
方法)和类实例方法。 内置方法由支持它们的类型来描述。
如果你通过一个实例来访问方法(即定义在类命名空间内的函数),你会得到一个特殊对象: 绑定方法 (或称 实例方法) 对象。 当被调用时,它会将 self
参数添加到参数列表。 绑定方法具有两个特殊的只读属性: m.__self__
与函数对象类似,绑定方法对象也支持获取任意属性。 但是,由于方法属性实际上保存于下层的函数对象中 (meth.__func__
),因此不允许设置绑定方法的方法属性。 尝试设置方法的属性将会导致引发 。 想要设置方法属性,你必须在下层的函数对象中显式地对其进行设置:
代码对象被具体实现用来表示“伪编译”的可执行 Python 代码,例如一个函数体。 它们不同于函数对象,因为它们不包含对其全局执行环境的引用。 代码对象由内置的 函数返回,并可通过从函数对象的 __code__
属性从中提取。 另请参阅 模块。
可以通过将代码对象(而非源码字符串)传给 或 内置函数来执行或求值。
类型对象表示各种对象类型。 对象的类型可通过内置函数 来获取。 类型没有特殊的操作。 标准库模块 定义了所有标准内置类型的名称。
此对象会由不显式地返回值的函数所返回。 它不支持任何特殊的操作。 空对象只有一种值 None
(这是个内置名称)。 type(None)()
会生成同一个单例。
该对象的写法为 None
。
此对象常被用于切片 (参见 )。 它不支持任何特殊的操作。 省略符对象只有一种值 (这是个内置名称)。 type(Ellipsis)()
会生成 单例。
此对象会被作为比较和二元运算被应用于它们所不支持的类型时的返回值。 请参阅 了解更多信息。 未实现对象只有一种值 NotImplemented
。
布尔值是两个常量对象 False
和 True
。 它们被用来表示逻辑上的真假(不过其他值也可被当作真值或假值)。 在数字类的上下文中(例如被用作算术运算符的参数时),它们的行为分别类似于整数 0 和 1。 内置函数
可被用来将任意值转换为布尔值,只要该值可被解析为一个逻辑值(参见之前的 部分)。
有关此对象的信息请参阅 。 其中描述了栈帧对象、回溯对象以及切片对象等等。
语言实现为部分对象类型添加了一些特殊的只读属性,它们具有各自的作用。 其中一些并不会被 内置函数所列出。
-
一个字典或其他类型的映射对象,用于存储对象的(可写)属性。
-
由类对象的基类所组成的元组。
-
类、函数、方法、描述器或生成器实例的名称。
-
类、函数、方法、描述器或生成器实例的 。
-
此属性是由类组成的元组,在方法解析期间会基于它来查找基类。
-
此方法可被一个元类来重载,以为其实例定制方法解析顺序。 它会在类实例化时被调用,其结果存储于 之中。
-
每个类都存有对直接子类的弱引用列表。本方法返回所有存活引用的列表。列表的顺序按照子类定义的排列。例如:
}
这是一个Google笔试题,我5年前看到的。
设有一整数数组,元素个数为N,求其中N-1个元素相乘的最大乘积。
1. 时间复杂度尽可能低
单元测试我写好了,敢上擂台的同学,把代码贴到下面,我来检查能通过几个单元测试,哈哈。
挑擂结果(有两个测试用例我只占了个位,没写具体的数据。下面的结果都不包含这两个用例)
JoyQi 目前最接近标准答案的,只有2个测试用例没通过,时间复杂度,我目测是没到最小,但跟我写的也不相伯仲,如果用C语言来实现,是循环更耗费时间还是大数相除更耗费时间就不好说了。
Sunyanzi 的还差三个测试用例没通过 *参数输入正确的正常流程 *参数输入错误的异常流 * 本来根据根据负数个数奇偶性、正数有无可以分成四种情况 * 但这四种情况明显可以归并到这一种,因此不再分成四个条件来写 * 零的个数等于1 偶数个负数 有正数 * 零的个数等于1 偶数个负数 无正数 * 零的个数等于1 奇数个负数 有正数 * 零的个数等于1 奇数个负数 无正数 *
零的个数小于1 偶数个负数 有正数 * 零的个数小于1 偶数个负数 无正数 * 零的个数小于1 奇数个负数 有正数 * 零的个数小于1 奇数个负数 无正数 * 输入的参数不是数组 * 数组元素个数小于2个 * 数组元素不全是整数 * 如果代码中用整形来记录【零、正数、负数】的个数,输入的数组元素个数超过int型上限,就会造成数据溢出
//这种极端情况不支持,也不测试,写在这里仅仅表示我考虑到这点了 * N-1个元素的乘积超过PHP能表达的上限,就会造成数据溢出 //这种情况暂时不支持,也不测试,写在这里仅仅表示我考虑到这点了 }公布答案了:我的函数实现 * 先遍历数组找出零、负数、正数的数量 * 只做统计,不排序,不做乘法 * 0的个数大于1,任意取N-1个元素,其乘积都是0
* 故无须再判断正数和负数的个数 * 最大乘积只能是0,无需判断正数个数 * 除0之外的N-1个整数乘积最大 * 除【绝对值最小的负数】之外的N-1个整数乘积最大 * 除【绝对值最小的正数】之外的N-1个整数乘积最大 * 除【绝对值最大的负数】之外的N-1个整数乘积最大 * 若需要计算N-1个元素的乘积
- 这是我做《如何设计完备可靠的测试用例》培训用的一个代码示范,在github上开源的:,会持续更新,敬请关注
- 我贴出来的测试用例只有“参数输入正确的正常流程”是100%做到了MECE(完全穷尽,彼此独立),“参数输入错误的异常流”还没做到MECE,极端情况的“白盒测试”就更谈不上MECE了,而且也没写测试方法体
}