Python列表与元组

1.序列

字符串(str)、列表(list)和元组(tuple)都属于序列(sequence)类型。
序列又分为可变序列(mutable)和不可变序列(immutable),可变指的是可修改序列的元素,列表属于可变序列,字符串和元组都属于不可变序列。

# 列表使用中括号表示
>>> nums = [1,2,3]
>>> type(nums)
<class 'list'>
>>> nums[1] = 0 # 列表是可变序列
>>> nums
[1, 0, 3]

# 元组使用圆括号表示
>>> seqs = (4,5,6)
>>> type(seqs)
<class 'tuple'>
>>> seqs[1] = 0 # 元组是不可变序列
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> seqs
(4, 5, 6)

1.1序列操作

序列类型支持的一些通用操作(即可变和不可变序列均支持)如下表:

OperationResult
xins如果s中的某项等于x,则结果为True,否则为False
x not in s如果s中的某项等于x,则结果为False,否则为True
s + ts与t相拼接
s * n或n * s相当于s与自身进行n次拼接
s[i]s的第i项,起始为0
s[i:j]s从i到j的切片
s[i:j:k]s从i到j步长为k的切片
len(s)s的长度
min(s)s的最小项
max(s)s的最大项
s.index(x[,i[,j]])x在s中首次出现项的索引号(索引号在i或其后且在j之前)
s.count(x)x在s中出现的总次数

下面对以上操作进行示例演示:

  • x in s
>>> 1 in [1,2,3]
True
>>> 4 in [1,2,3]
False
  • x not in s
>>> 4 not in (1,2,3)
True
>>> 1 not in (1,2,3)
False
  • s + t
>>> [1,2] + [3,4]
[1, 2, 3, 4]
>>> (5,6) + (7,8)
(5, 6, 7, 8)
  • s * n或n * s
>>> [1,2] * 2
[1, 2, 1, 2]
>>> 3 * 'w'
'www'
  • s[i]
>>> [1,2,3][0]
1
>>> 'abcd'[-1]
'd'
  • s[i:j]
>>> [1,2,3][0:2]
[1, 2]
>>> [1,2,3][:2] # i可以省略,默认值为0
[1, 2]
>>> [1,2,3][1:] # j可以省略,默认值为len(s)
[2, 3]
>>> [1,2,3][:] # i和j同时省略则相当于对s进行了拷贝
[1, 2, 3]
>>> [1,2,3][2:1] # 如果j<=i,则返回一个空列表
[]
>>> [1,2,3][1:-1] # i和j也可以是负数,如果是负数则会被转换为lens(s)+i/j
[2]
>>> [1,2,3][1:2] # [1:-1]就相当于[1:len(s)+(-1)] = [1:3-1] = [1:2]
[2]
>>> [1,2,3][1:5] # 如果i或j大于len(s),则被转换为len(s)
[2, 3]
  • s[i:j:k]
>>> [1,2,3][0:3:2] # 设定步长k为2,默认为1
[1, 3]
>>> [1,2,3][2:0:-1] # 相当于取2,2-1,2+n*(-1),...
[3, 2]

# k为负数时,i或j的默认值会倒转
# k为正数时,i和j的默认值分别为0,len(s)
# k为负数时,i和j的默认值分别为len(s)-1,0,且包含第0个元素
>>> [1,2,3][::-1]
[3, 2, 1]

# k不能为0
>>> [1,2,3][::0]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: slice step cannot be zero
  • len(s)
>>> len([1,2,3])
3
>>> len('abc')
3
  • min(s)
>>> min([1,2,3])
1
>>> min('abc')
'a'
>>> min([1,2,'a']) # 序列中的元素必须是相同类型的
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: '<' not supported between instances of 'str' and 'int'
  • max(s)
>>> max([1,2,3])
3
>>> max('abc')
'c'
>>> max([1,2,'a']) # 序列中的元素必须是相同类型的
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: '>' not supported between instances of 'str' and 'int'
  • s.index(x[,i[,j]])
>>> [1,2,3].index(1)
0
>>> [1,2,3].index(4)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: 4 is not in list
  • s.count(x)
>>> [1,2,1].count(1)
2
>>> [1,2,1].count(3)
0

2.列表

列表属于不可变序列(immutables sequence),列表定义除了用中括号([])以外,还可以使用内置函数list()把其它序列类型转换为列表:

>>> list('abc')
['a', 'b', 'c']
>>> list((1,2,3))
[1, 2, 3]

2.1列表操作
列表除了支持序列类型的通用操作外,还支持以下这些可变序列独有的操作:

OperationResult
s[i] = x将s的第i项替换为x
s[i:j] = t将s从i到j的切片替换为可迭代对象t的内容
del s[i:j]等同于s[i:j] = []
s[i:j:k] = t将s[i:j:k]的元素替换为t的元素
s.append(x)将x添加到序列的末尾(等同于s[len(s):len(s)] = [x])
s.clear()从s中移除所有项(等同于del s[:])
s.copy()创建s的浅拷贝(等同于s[:])
s.extend(t) 或 s + t用t的内容扩展s(基本等同于s[len(s):len(s)] = [t])
s*=n使用s的内容重复n次来对其进行更新
s.insert(i,x)在由i给出的索引位置将x插入s(等同于s[i:j] = [x])
s.pop([i])提取在i位置上的项,并将其从s中移除
s.remove(x)删除s中第一个s[i]等于x的项目
s.reverse()就地将列表中的元素逆序

下面对以上操作进行示例演示:

  • s[i] = x
>>> nums = [1,2,3]
>>> nums[1] = 0
>>> nums
[1, 0, 3]
  • s[i:j] = t
>>> nums = [1,2,3]
>>> nums[1:3] = [0,0] # 把第1到3-1范围的元素替换为[0,0]
>>> nums
[1, 0, 0]
>>> nums[1:3] = [] # 把第1到3-1范围的元素删除
>>> nums
[1]
>>> nums[:] = [] # 清空整个列表
>>> nums
[]
  • del s[i:j]
>>> nums = [1,2,3]
>>> del nums[1:3]
>>> nums
[1]
  • s[i:j:k] = t
>>> nums = [1,2,3]
>>> nums[0:3:2] = [5,6] # 把第0,0+2两个元素分别替换为[5.6]中的元素
>>> nums
[5, 2, 6]
>>> nums[0:3:2] = [5] # t的元素个数必须和[i:j:k]切割出来的元素个数相等
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: attempt to assign sequence of size 1 to extended slice of size 2
  • del s[i:j:k]
>>> nums = [1,2,3]
>>> del nums[0:3:2]
>>> nums
[2]
  • s.append(x)
>>> nums = [1,2,3]
>>> nums.append(4)
>>> nums
[1, 2, 3, 4]
  • s.clear()
>>> nums = [1,2,3]
>>> nums.clear()
>>> nums
[]
  • s.copy()
>>> nums = [1,2,3]
>>> nums_copy = nums.copy()
>>> nums_copy
[1, 2, 3]
  • s.extend(t) 或 s + t
>>> nums = [1,2,3]
>>> nums.extend([4,5])
>>> nums
[1, 2, 3, 4, 5]
>>> nums += [6,7]
>>> nums
[1, 2, 3, 4, 5, 6, 7]
  • s*=n
>>> nums = [1,2,3]
>>> nums *= 2
>>> nums
[1, 2, 3, 1, 2, 3]
>>> nums *= -1 # 如果n小于等于0,则s被清空
>>> nums
[]
  • s.insert(i,x)
>>> nums = [1,2,3]
>>> nums.insert(1,4)
>>> nums
[1, 4, 2, 3]
>>> nums[1:1] = [5] # 等同于nums.insert(1,5)
>>> nums
[1, 5, 4, 2, 3]
  • s.pop([i])
>>> nums = [1,2,3]
>>> nums.pop() # 参数i默认为-1
3
>>> nums
[1, 2]
>>> nums.pop(0) # 也可以pop指定位置的元素
1
>>> nums
[2]
  • s.remove(x)
>>> chars = ['a','b','c']
>>> chars.remove('b')
>>> chars
['a', 'c']
>>> chars.remove('f') # 如果s中不存在值为x的元素,则报ValueError
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: list.remove(x): x not in list
  • s.reverse()
>>> nums = [1,2,3]
>>> nums.reverse()
>>> nums
[3, 2, 1]

2.2列表排序

列表除了支持序列通用操作和可变序列操作外,列表还实现了一个单独的方法sort:

  • list.sort(key=None, reverse=False)
    sort是一个就地排序方法,默认升序排序,如果reverse参数为True,则是进行降序排序。
    key可以接受一个函数,对待排序的对象进行预处理后再进行排序。
>>> nums = [2,3,1]
>>> nums.sort()
>>> nums
[1, 2, 3]
>>> nums.sort(reverse=True)
>>> nums
[3, 2, 1]

>>> ids = ['lily-02','tom-01','jack-03']
>>> ids.sort()
>>> ids
['jack-03', 'lily-02', 'tom-01']
>>> ids.sort(key=lambda s:s.split('-')[-1])
>>> ids
['tom-01', 'lily-02', 'jack-03']

2.3列表推导式
列表推导式提供了一种简洁的方式来创建列表,比如需要创建一个1~10的平方数的列表,只需要像这样一行代码即可完成:

>>> [x**2 for x in range(1,11)]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

列表推导式也支持在for后边添加if语句:

>>> [x for x in range(1,11) if x%2 == 0]
[2, 4, 6, 8, 10]

列表推导式也支持嵌套:

>>> [(x,y) for x in [1,2] for y in [3,4]]
[(1, 3), (1, 4), (2, 3), (2, 4)]

# 上面的推导式与以下嵌套循环作用相同
>>> combs = []
>>> for x in [1,2]:
...     for y in [3,4]:
...             combs.append((x,y))
...
>>> combs
[(1, 3), (1, 4), (2, 3), (2, 4)]

2.4浅拷贝与深拷贝
列表支持嵌套列表或嵌套其它可变对象,对于列表自带的copy方法和切片式拷贝,以及*(repeation),都只是一个浅拷贝,下面举例对浅拷贝进行说明:

>>> nested_nums = [1,[2,3],4]
>>> copy_nested_nums = nested_nums.copy() # 浅拷贝,等同于nested_nums[:]

# 修改原始列表中非嵌套元素,拷贝列表不受影响
>>> nested_nums[0] = 9
>>> nested_nums
[9, [2, 3], 4]
>>> copy_nested_nums
[1, [2, 3], 4]

# 修改原始列表中嵌套列表的元素,拷贝列表受影响
>>> nested_nums[1][0] = 9
>>> nested_nums
[9, [9, 3], 4]
>>> copy_nested_nums
[1, [9, 3], 4]

如果相应避免上面的浅拷贝的情况,可以使用copy.deepcopy函数进行深拷贝:

>>> nested_nums = [1,[2,3],4]
>>> import copy
>>> copy_nested_nums = copy.deepcopy(nested_nums)
>>> nested_nums[1][0] = 9
>>> nested_nums
[1, [9, 3], 4]
>>> copy_nested_nums # 深拷贝的列表不受影响
[1, [2, 3], 4]

3.Range

range是一个内置类型,可以用来创建一个不可变序列(immutable),定义如下:

class range(stop)
class range(start, stop[, step])start到stop范围内(不包含stop),以步长为step,产生一个序列。

start,stop,step均为int类型,如果只是传入一个参数,这个参数会被当做stop:

>>> [i for i in range(3)]
[0, 1, 2]

也可以传入2个参数,则分别会被当做start和stop:

>>> [i for i in range(1,3)]
[1, 2]

还可以设定步长(stop),步长默认值为1:

>>> [i for i in range(1,10,2)]
[1, 3, 5, 7, 9]

如果步长step为负数,那么应该满足start >= stop:

>>> [i for i in range(3,0,-1)]
[3, 2, 1]

和list相比,range类型更节约内存,因为list占用内存大小是根据元素的多少而变化,而range生成的实例只是记录了一下计算方法,不管范围多大,都占用固定大小的内存,在每一次for循环时才实时计算出当前的元素内容:

>>> nums = [1,2,3]
>>> import sys
>>> sys.getsizeof(nums)
80
>>> r = range(1,4)
>>> sys.getsizeof(r)
48
>>> nums = [1,2,3,4]
>>> sys.getsizeof(nums)
88
>>> r = range(1,5)
>>> r
range(1, 5)
>>> sys.getsizeof(r)
48

4.元组(tuple)

元组和列表类似,都是序列,不同的是元组是不可变序列(immuatble sequence),元组的定义使用圆括号,也可以使用内置关键字tuple,将其他序列转换为元组:

>>> t = (1,2,3)
>>> t
(1, 2, 3)
>>> t = 1,2,3 # 如果元素个数超过1个,也可以不使用圆括号
>>> t
(1, 2, 3)

# 只有1个元素的元组需要用圆括号括起来,并且在末尾添加一个逗号(,)
# 这样做是为了和数学符号的圆括号进行区分
>>> t = (1,)
>>> t
(1,)
>>> tuple([1,2,3]) # 把列表转换为元组
(1, 2, 3)

元组作为不可变序列,一旦定义后,其中的元素不能被修改:

>>> t = (1,2,3)
>>> t[0] = 5
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment

但是元组里的可变类型的内容是可以被修改的:

>>> t = (1,[2,3],4)
>>> t[1][0] = 3
>>> t
(1, [3, 3], 4)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值