序列类型(list、tuple、range)及其操作
Python 里有几个复合数据类型统称为序列类型(sequence,注意 sequence 本身并不是 Python 内部类型的名字)。这几个序列类型有一些共性,主要是对这些类型的对象都可以做一些操作。

有关序列类型的详细情况见 Python 标准库手册 4.6 节。下面介绍其中一些主要情况。

在讨论(和操作)序列的时候经常要用到下标i,下标范围 i : j 和带步进值的下标 i : j : k,将它们放在表示序列对象的表达式(如变量)后面的一对方括号里。现在对这些表示方式做一些说明。假设 s 是序列,其元素下标为 m, m+1, …, n-1:

  1. 这时说 s 的下标是"从 m 到 n"(from m to n)。这种说法意味着 s 的合法下标包含 m 但不包含 n。

  2. 对表达式 s[i] 求值时,如果 i 的值在从 m 到 n 的范围内("从 m 到 n" 按上一条的定义),将得到 s 里下标为 i 的元素的值;否则系统将报一个 IndexError 错误。

  3. 表达式 s[i : j] 得到 s 里从 i 到 j 的切片(注意,"从 i 到 j" 的意思同第1条里的 "从 m 到 n")。如果 i < m,s[i : j] 相当于 s[m : j];如果 j > n,s[i : j] 相当于 s[i : n]。如果 i >= n 或者 j <= m,得到的将是相应的空序列(空表,空字符串等)。

  4. 表达式 s[i :] 相当于 s[i : n];表达式 s[: j] 相当于 s[m : j];s[:] 相当于 s[m : n]。

  5. s[i : j : k] 得到 s 的切片的情况与 s[i : j] 类似,只是其确定的元素从下标 i 开始,下标按 k 步进增长,直至但不包括下标 j。(s[i : j] 等效于 s[i : j : 1])。

  6. 表达式 s[i] 的值是 s 的下标为 i 的元素,表达式 s[i : j] 等切片表达式的值是一个与 s 同类型的序列(另一个序列),其中包含上面说明的元素。再如 s[:] 建立 s 的一个新拷贝。

可变和不可变的序列类型

有的序列类型是可变(mutable)类型,它们的对象在建立之后,可以通过一些操作改变其内部状态。Python 标准类型中只有 list 是可变序列类型。range 和 tuple 都是不可变的序列类型,也就是说,程序里可以创建这两个类型的对象,但不能改变已有的对象。当然,完全可以利用(基于)已有的对象创建与之略有不同的对象。

不可变序列类型只支持创建新对象(可以是基于已有的对象创建新对象),检查已有对象的操作;可变类型还支持一些修改已有对象的操作。

所有序列类型都支持的操作

下面的 s, t 表示序列,x 表示元素,m, n, i, j, k 表示整数。

所有类型都支持的操作分为几类。

  1. 检查元素包含关系,计算结果得到一个逻辑值:
    • x in s 在 x 是 s 的元素时返回 true,否则返回 false
    • x not in s 在 x 是 s 的元素时返回 false,否则返回 true

  2. 构造新序列,结果是得到的新序列:
    • s + t 得到两个序列的拼接序列,其中先是 s 的所有元素,然后是 t 的所有元素
    • s * n 或 n * s 得到是 s 的 n 个拷贝的拼接序列
    • s[i : j] 得到 s 的从 i 到 j 的切片,是一个序列
    • s[i : j : k] 得到 s 里从 i 到 j 间距为 k 的切片,是一个序列

  3. 取序列的元素,得到序列的元素对象:
    • s[i] 得到 s 的第 i 个元素
    • min(s) 得到 s 里的最小元素,显然要求 s 的元素可以比较大小
    • max(s) 得到 s 里的最大元素

  4. 其他
    • s.count(x) 得到 x 在 s 里出现的次数
    • s.index(x) 得到 x 在 s 里第一次出现的位置(下标);s.index(x, m) 得到 x 在 s 里在下标 m 之后第一次出现的位置;s.index(x, m, n) 得到 x 在 s 里下标 m 到 n 范围里第一次出现的位置。如果在 s 里或者在 s 的指定范围里没有 x,系统将给出一个 ValueError

不变序列类型的特有操作

这种操作只有一个:对不变序列可以用 hash(s) 得到一个特殊的整数值。具体值依赖于具体的 Python 实现。其用途在讨论字典数据类型(dict)时介绍。

可变序列类型的特有操作

可变序列类型特殊的操作都是修改序列对象的操作。操作可以分为几组,其中前两组操作是命令而不是表达式,其语义是操作的效果(修改 s 的结果),而不是得到一个值。
  1. 修改序列元素或序列中的切片(包括删除。除被修改的元素外其他元素不变):
    • s[i] = x 使得 s 中下标为 i 的元素变成 x
    • s[i : j] = t 把 s 里从 i 到 j 的切片换为 t,注意 t 也是一个序列,对其长度没有要求,因此这个操作可能改变相应序列对象的长度以及位于 t 的元素之后的元素的下标。注意,并不要求 t 是与 s 同样类型的序列,例如 s 是 list 时 t 完全可以是 range 或 tuple
    • s[i : j : k] = t 把 s 中由 i : j : k 确定的切片的元素顺序换成 t 里对应的元素。这里要求 t 的长度和这个切片的长度相同(上一操作没有这个要求)
    • del s[i : j] 相当于 s[i, j] = [ ]
    • del s[i : j : k] 从 s 里删除切片 s[i : j : k] 的元素

  2. 修改 s 的几个函数:
    • s.append(x) 把 x 加入 s 作为其最后一个元素(前面的元素不变)
    • s.extend(t) 修改 s,将 t 的所有元素连接在 s 已有元素之后
    • s.insert(i, x) 在 s 中下标 i 确定的位置插入 x(i 之后原有元素的下标加 1)
    • s.remove(x) 从 s 里删除 x 的第一个出现(删除第一个等于 x 的元素)。如果 s 里没有 x 则系统报告 ValueError 错误
    • s.reverse() 将 s 里元素反转,原来最前面的元素变成最后的元素,反之亦然
    • s.clear() 相当于 del s[:]

  3. 还有两个操作得到值,可以用作表达式给变量赋值等:
    • s.copy() 得到 s 的一个拷贝,相当于 s[:]
    • s.pop([i]) 得到 s 里下标为 i 的元素,并从 s 里将其删除。注意这个操作很特殊,它既有一个值(以 s 的一个元素为值),也有操作的效果(从 s 里删除一个元素)。如果不指定元素,s.pop() 返回 s 的最后一个元素并删除它
请注意最后这个操作,它比较特殊:在执行中它不但能返回一个值,还会修改被操作的对象。表达式的基本功能(语义)就是能求出一个值,这是表达式的主要作用。表达式 s.pop() 不但能求出一个值,还会修改 s 约束的那个对象,因此我们说这个表达式有"副作用"(side effect)。

序列的比较

序列类型 list 和 tuple 的对象可以做相等比较,还可以比较大小(大于、大于等于、小于、小于等于)。这些比较用常规的比较运算符。list 和 tuple 之间不能比较。

两个 list 对象(或两个 tuple 对象)相等,当且仅当它们的长度相同,而且对应的元素分别相等;否则就是不相等。

一个 list 对象小于(大于)另一个 list 对象(或者一个 tuple 对象小于(大于)另一个 tuple 对象),按照所谓的 "字典序" 确定:从前向后逐个比较两者的元素,如果在遇到第一对不相等元素时是第一个对象的元素较小,这认为前一对象小于后一对象;否则就是大于。如果做比较的元素都相等,但第一个 list(或 tuple)的元素先用完,那么也认为它较小;否则就是较大。

由于一个 list 或 range 对象的元素可以具有不同类型,有些比较的合理性也是有疑问的。例如,[1, 2] < [2, 'abc'] 将得到 True 的结果。

本页及相关页面(除另声明者外)由裘宗燕创建维护,可自由用于各种学习活动。其他使用需得到作者许可。