Python基础:序列

时间:2023-07-16 10:15:38

一、概述

序列类型(Sequence Types)类似于C中的数组,它是包含一组成员的连续列表,这些成员紧邻排列,并且可以通过序号(下标偏移量)访问其中的一个或多个成员。序列类型的示意图如下所示:

Python基础:序列

Python中最核心的序列类型共有3种:字符串(str和unicode)、列表(list)和元组(tuple)。

二、操作

序列类型支持的主要操作如下:

操作 说明
s[i] s中第i个成员(从0开始)
s[i:j] s中从i到j的切片
s[i:j:k] s中从i到j的切片,步长为k
s * n, n * s s的n份(浅)拷贝的串联
s + t s与t的串联
x in s 如果x是s的成员,为True;否则,为False
x not in s 如果x是s的成员,为False;否则,为True
enumerate(s) 返回一个enumerate对象,该对象生成由(i, s[i])组成的元组
len(s) s的长度
list(iter) 把可迭代对象转换为列表
max(s) s中的最大值
min(s) s中的最小值
reversed(s) 返回一个迭代器,访问该迭代器得到的序列与s逆序
sorted(s) 返回一个列表,该列表是对s排序后的结果
str(obj) 把对象转换为字符串(对象的字符串表示)
sum(s[, start]) s中成员与start的总和(只能用于数值列表或数值元组,字符串用''.join(s))
tuple(iter) 把可迭代对象转换为元组
unicode(obj) 把对象转换为Unicode字符串(使用默认编码)
zip(s1, s2, ...) 返回一个列表:[(s1[0], s2[0], ...), (s1[1], s2[1], ...), ...]

以上操作的示例如下:

>>> s = 'abcedf'
>>> l = [0, 1, 2, 3, 4, 5]
>>> t = tuple(l)
>>>
>>> s[0], l[0], t[0]
('a', 0, 0)
>>> s[2:5], l[2:5], t[2:5]
('ced', [2, 3, 4], (2, 3, 4))
>>> s[2:5:2], l[2:5:2], t[2:5:2]
('cd', [2, 4], (2, 4))
>>> s * 2, 2 * s
('abcedfabcedf', 'abcedfabcedf')
>>> list(s) + l
['a', 'b', 'c', 'e', 'd', 'f', 0, 1, 2, 3, 4, 5]
>>> 6 in l, 6 not in l
(False, True)
>>>
>>> for i, x in enumerate(s):
... print i, x
...
0 a
1 b
2 c
3 e
4 d
5 f
>>> len(s), len(l), len(t)
(6, 6, 6)
>>> max(s), min(s)
('f', 'a')
>>> for x in reversed(t):
... print x,
...
5 4 3 2 1 0
>>> sorted([7, 4, 8, 0, 9])
[0, 4, 7, 8, 9]
>>> str(t)
'(0, 1, 2, 3, 4, 5)'
>>> unicode(l)
u'[0, 1, 2, 3, 4, 5]'
>>> sum(t), sum(t, 5)
(15, 20)
>>> zip(s, l, t)
[('a', 0, 0), ('b', 1, 1), ('c', 2, 2), ('e', 3, 3), ('d', 4, 4), ('f', 5, 5)]

三、切片

1、[]

“[]”用于访问序列中的单个元素,如可以用s[i]访问序列s中的第i个元素,其中对i的取值范围有以下限制:

  • 如果i非负,则i必须在[0, N-1]范围内,否则访问会引发越界异常
  • 如果i为负,则i必须在[-N, -1]范围内,否则访问会引发越界异常

以上描述中,N=len(s)即序列的长度。

序列的 下标编号规则 参考『概述』一节中的“序列类型示意图”,实际上,对于序列s而言:

  • i非负时,Python使用s[i]去访问序列
  • i为负时,Python使用s[N+i]去访问序列

“[]”的操作示例如下:

>>> s = 'abcdef' # N=len(s)等于6,因此非负i的范围[0, 5],负i的范围[-6, -1]
>>>
>>> s[0] # 0非负,且0在[0, 5]范围内
'a'
>>>
>>> s[6] # 0非负,但6>5,越界异常
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: string index out of range
>>>
>>> s[-1] # -1为负,且-1在[-6, -1]范围内
'f'
>>>
>>> s[-7] # -7为负,但-7<-6,越界异常
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: string index out of range

2、[:]和[::]

“[:]”和“[::]”用于访问序列中的多个元素(又称切片,slice),因为在功能上“[:]”完全可以看作是“[::1]”(即步长为1)的简写,所以理解“[::]”是掌握切片操作的关键。

切片s[i:j:k]是一个子序列,它由序列s中下标在 [i, j)(左闭右开区间)范围内的一些成员构成,这些成员的下标分别为i, i+k, i+2*k, ...。

在切片操作中,i、j、k的取值有以下特点(具体细节可以参考 Python2.7.5源码 的Python-2.7.5/Objects/sliceobject.c中的PySlice_GetIndicesEx函数):

  • k不能为0;省略k或k为None时,令k=1
  • k为正时
    • 如果省略i或i为None,则令i=0
    • 如果省略j或j为None,则令j=N
    • 如果i为负,则令i=i+N,此时如果i仍然为负,则令i=0;j类似
    • 如果i大于等于N,则令i=N;j类似
  • k为负时
    • 如果省略i或i为None,则令i=N-1
    • 如果省略j或j为None,则令j=-1
    • 如果i为负,则令i=i+N,此时如果i仍然为负,则令i=-1;j类似
    • 如果i大于等于N,则令i=N-1;j类似

特别地,经过上述计算后,如果i、j、k的最终取值满足以下情况,则切片s[i:j:k]对应的子序列为空:

  • k为正,且i大于等于j
  • k为负,且i小于等于j

“[:]”和“[::]”的操作示例如下:

>>> s = 'abcdef' # N=len(s)等于6

# 1. 省略k或k为None时,k=1
>>> s[0:4], s[0:4:None], s[0:4:1]
('abcd', 'abcd', 'abcd') # 2. k为正时
>>> s[:2] # 省略i时,令i=0,因此s[:2]等价于s[0:2]
'ab'
>>> s[2:] # 省略j时,令j=N,因此s[2:]等价于s[2:6]
'cdef'
>>> s[2:-1] # j为负时,令j=-1+N,因此s[2:-1]等价于s[2:5]
'cde'
>>> s[2:-10] # j为负时,j=-10+N等于-4仍然为负,令j=0,因此s[2:-10]等价于s[2:0]
''
>>> s[10:2] # i大于N时,令i=N,因此s[10:2]等价于s[6:2]
'' # 3. k为负时
>>> s[:2:-1] # 省略i时,令i=N-1,因此s[:2:-1]等价于s[5:2:-1]
'fed'
>>> s[2::-1] # 省略j时,令j=-1,因此s[2::-1]的成员为s[2]、s[1]、s[0],但不等价于s[2:-1:-1]
'cba'
>>> s[2:-1:-1] # j为负时,令j=-1+N,因此s[2:-1:-1]等价于s[2:5:-1]
''
>>> s[2:-10:-1] # j为负时,j=-10+N等于-4仍然为负,令j=-1,因此s[2:-10:-1]等价于s[2::-1]
'cba'
>>> s[10:2:-1] # i大于N时,令i=N-1,因此s[10:2:-1]等价于s[5:2:-1]
'fed' >>> s, s[:], s[0:6], s[::], s[0:6:None], s[0:6:1] # 序列s的各种等价表示
('abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef', 'abcdef')
>>>
>>> s[::-1] # 序列s的逆序表示
'fedcba'