Python序列概述
§ Python序列类似于其他语言中的数组,但功能要强大很多。
§ Python中常用的序列结构有列表、元组、字符串,字典、集合以及range等对象也支持很多类似的操作。
§ 列表、元组、字符串支持双向索引,第一个元素下标为0,第二个元素下标为1,以此类推;最后一个元素下标为-1,倒数第二个元素下标为-2,以此类推。
2.1 列表
2.1.1 定义
列表是Python中内置有序可变序列,列表的所有元素放在一对中括号“[]”中,并使用逗号分隔开;
一个列表中的数据类型可以各不相同,可以同时分别为整数、实数、字符串等基本类型,甚至是列表、元组、字典、集合以及其他自定义类型的对象。
例如:
[1,2,3,2.4,5]
[0.01,"abc",[1,2,3],(2,1,3,4,7),{5:6}]
2.1.2 列表的创建与删除
创建
①使用“=”直接将一个列表赋值给变量即可创建列表对象。例如:a_list = [],b_list = [1,2,3]
②使用list()函数将元组、range对象、字符串或其他类型的可迭代对象类型的数据转换为列表。
例如:a_list = list("Hello") 将字符串 "hello" 转换成列表 ['H','e','l','l','o']
删除
当不再使用时,使用del命令删除整个列表
例如:
>>>x =[1,2,3]
>>>del x[1] #删除指定位置元素
>>>x
[1,3]
>>>del x #删除整个列表
>>>x
Traceback (most recent call last):
File "<pyshell#6>", line 1, in <module>
x
NameError: name 'x' is not defined
2.1.2 列表元素的增加
append()
向列表尾部追加一个元素,不改变其内存首地址,属于原地操作。
例如:
>>>x = [1,2,3]
>>>x.append(4)
>>>x
[1,2,3,4]
insert()
向列表任意位置插入一个元素,不改变其内存首地址,属于原地操作。
例如:
>>>x = [1,3,4]
>>>x.insert(1,2)
>>>x
[1,2,3,4]
extend()
将另一个迭代对象的所有元素添加至该列表对象尾部,不改变其内存首地址,属于原地操作。
例如:
>>>x = [1,2]
>>>x.extend([3,4])
>>>x
[1,2,3,4]
运算符" + " 和" * "
并不是真的为列表添加元素,而是创建一个新列表,不属于原地操作,而是返回新列表。
>>> x = [1,2,3]
>>>x = x + [4]
>>>x
[1,2,3,4]
>>>x = x*2
>>>x
[1,2,3,4,1,2,3,4]
2.1.3 列表元素的删除
pop()
使用列表的pop()方法删除并返回指定(默认为最后一个)位置上的元素,如果给定的索引超出了列表的范围则抛出异常。
例如:
>>>x = [1,2,3,4]
>>>x.pop() #弹出并返回尾部元素
4
>>>x.pop(1) #弹出并返回指定位置的元素
>>>2
remove()
删除首次出现的指定元素,如果列表中不存在要删除的元素,则抛出异常。
例如:
>>>x = [1,2,2,3,4]
>>>x.remove(2)
>>>x
[1,2,3,4]
clear()
清空列表。
例如:
>>>x = [1,2,3,4]
>>>x.clear()
>>>x
[ ]
del
删除列表中的指定位置上的元素。
例如:
>>>x = [1,2,3,4]
>>>del x[1]
>>>x
[1,3,4]
2.1.4 列表元素访问与计数
count()
统计指定元素在列表对象中出现的次数。
例如:
>>> x =[1,2,3,3,4,5]
>>>x.count(3)
2
>>>x.count(0)
0
index()
获取指定元素首次出现的下标,若列表对象中不存在指定元素,则抛出异常。
例如:
>>>x = [1,2,3,2,2,4]
>>>x.index(2)
1
in
测试列表中是否存在某元素
例如:
>>>x = [1,2,3,4]
>>>3 in x
True
>>>5 in x
False
2.1.5 列表排序
sort()
按照指定规则对所有元素进行排序,默认规则是直接比较规则大小。
例如:
>>> aList = [3, 4, 5, 6, 7, 9, 11, 13, 15, 17]
>>> import random
>>> random.shuffle(aList) #随机降序
>>> aList
[3, 4, 15, 11, 9, 17, 13, 6, 7, 5]
>>> aList.sort() #默认是升序排序
>>> aList.sort(reverse = True) #降序排序
>>> aList
[17, 15, 13, 11, 9, 7, 6, 5, 4, 3]
>>> aList.sort(key = lambda x:len(str(x))) #按转换成字符串的长度排序
>>> aList
[9, 7, 6, 5, 4, 3, 17, 15, 13, 11]
reverse()
将列表中所有元素原地逆序排列。
例如:
>>>x = [1,3,2,4,6,5]
>>>x.reverse()
>>>x
[5,6,4,2,3,1]
sorted()
使用内置函数sorted对列表进行排序并返回新列表,不对原列表做任何修改。
例如:
>>>x = [6,4,2,4,1]
>>> sorted(x) #升序排序
[1,2,4,4,6]
>>> sorted(aList,reverse = True) #降序排序
[6,4,4,2,1]
>>>x
[6,4,2,4,1]
reversed()
返回一个逆序排列后的迭代对象,不对原列表做任何修改。
>>>x =[1,5,3,6,2]
>>>list(reversed(x))
[2,6,3,5,1]
>>>x
[1,5,3,6,2]
2.1.6 切片操作
使用切片获取列表中的元素
>>> aList = [3, 4, 5, 6, 7, 9, 11, 13, 15, 17]
>>> aList[::] #返回包含元素的新列表
[3, 4, 5, 6, 7, 9, 11, 13, 15, 17]
>>> aList[::-1] #逆序的所有元素
[17, 15, 13, 11, 9, 7, 6, 5, 4, 3]
>>> aList[::2] #偶数位置,隔一个取一个
[3, 5, 7, 11, 15]
>>> aList[1::2] #奇数位置,隔一个取一个
[4, 6, 9, 13, 17]
>>> aList[3::] #从下标3开始的所有元素
[6, 7, 9, 11, 13, 15, 17]
>>> aList[3:6] #下标在[3, 6)之间的所有元素
[6, 7, 9]
>>> aList[0:100:1] #前100个元素,自动截断
[3, 4, 5, 6, 7, 9, 11, 13, 15, 17]
>>> a[100:] #下标100之后的所有元素,自动截断
[]
>>> x[100] #直接使用下标访问会发生越界
IndexError: list index out of range
使用切片来原地修改列表内容
>>> aList = [3, 5, 7]
>>> aList[len(aList):] = [9] #在尾部追加元素
>>> aList
[3, 5, 7, 9]
>>> aList[:3] = [1, 2, 3] #替换前3个元素
>>> aList
[1, 2, 3, 9]
>>> aList[:3] = [] #删除前3个元素
>>> aList
[9]
>>> aList = list(range(10))
>>> aList
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> aList[::2] = [0]*5 #替换偶数位置上的元素
>>> aList
[0, 1, 0, 3, 0, 5, 0, 7, 0, 9]
>>> aList[::2] = [0]*3 #切片不连续,两个元素个数必须一样多
ValueError: attempt to assign sequence of size 3 to extended slice of size 5
使用del与切片结合来删除列表元素
>>> aList = [3,5,7,9,11]
>>> del aList[:3] #删除前3个元素
>>> aList
[9, 11]
>>> aList = [3,5,7,9,11]
>>> del aList[::2] #删除偶数位置上的元素
>>> aList
[5, 9]
切片返回的是列表元素的浅复制
所谓浅复制,是指生成一个新的列表,并且把原列表中所有元素的引用都复制到新列表中。
例如:
>>> aList = [3, 5, 7]
>>> bList = aList #bList与aList指向同一个内存
>>> bList
[3, 5, 7]
>>> bList[1] = 8 #修改其中一个对象会影响另一个
>>> aList
[3, 8, 7]
>>> aList == bList #两个列表的元素完全一样
True
>>> aList is bList #两个列表是同一个对象
True
>>> id(aList) #内存地址相同
19061816
>>> id(bList)
19061816
>>> aList = [3, 5, 7]
>>> bList = aList[::] #切片,浅复制
>>> aList == bList #两个列表的元素完全一样
True
>>> aList is bList #但不是同一个对象
False
>>> id(aList) == id(bList) #内存地址不一样
False
>>> bList[1] = 8 #修改其中一个不会影响另一个
>>> bList
[3, 8, 7]
>>> aList
[3, 5, 7]
2.1.7 用于序列操作的常用内置函数
len()
返回列表中的元素个数,同样适用于元组、字典、集合、字符串等。
max()、 min()
返回列表中的最大或最小元素,同样适用于元组、字典、集合、range对象等。
sum()
对列表的元素进行求和运算。
zip()
返回可迭代的zip对象。
例如:
>>> aList = [1, 2, 3]
>>> bList = [4, 5, 6]
>>> cList = zip(a, b) #返回zip对象
>>> cList
<zip object at 0x0000000003728908>
>>> list(cList) #把zip对象转换成列表
[(1, 4), (2, 5), (3, 6)]
enumerate()
枚举列表元素,返回枚举对象,其中每个元素为包含下标和值的元组。该函数对元组、字符串同样有效。
例如:
>>> for item in enumerate('abcdef'):
print(item)
(0, 'a')
(1, 'b')
(2, 'c')
(3, 'd')
(4, 'e')
(5, 'f')
2.1.8 列表推导式
列表推导式使用非常简洁的方式来快速生成满足特定需求的列表,代码具有非常强的可读性。
语法形式:[表达式 for 变量 in 序列或迭代对象]
列表推导式在逻辑上相当于一个循环,只是形式更加简洁。
①使用列表推导式实现嵌套列表的平铺
>>> vec = [[1,2,3], [4,5,6], [7,8,9]]
>>> [num for elem in vec for num in elem]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
相当于:
>>> vec = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> result = []
>>> for elem in vec:
for num in elem:
result.append(num)
>>> result
[1, 2, 3, 4, 5, 6, 7, 8, 9]
②过滤不符合条件的元素
从列表中选择符合条件的元素组成新的列表
>>> aList = [-1,-4,6,7.5,-2.3,9,-11]
>>> [i for i in aList if i>0]
[6, 7.5, 9]
列出当前文件夹下所有Python源文件:
>>> import os
>>> [filename for filename in os.listdir('.') if filename.endswith(('.py', '.pyw'))]
③在列表推导式中使用多个循环,实现多序列元素的任意组合,并且可以结合条件语句过滤特定元素
>>> [(x, y) for x in range(3) for y in range(3)]
[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
>>> [(x, y) for x in [1, 2, 3] for y in [3, 1, 4] if x != y]
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
④使用列表推导式实现矩阵转置
>>>matrix = [ [1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
>>> [[row[i] for row in matrix] for i in range(4)]
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
也可以使用内置函数来实现矩阵转置:
>>>list(zip(*matrix)) #序列解包
[(1, 5, 9), (2, 6, 10), (3, 7, 11), (4, 8, 12)]
⑤列表推导式中可以使用函数或复杂表达式
>>> def f(v):
if v%2 == 0:
v = v**2
else:
v = v+1
return v
>>> [f(v) for v in [2, 3, 4, -1] if v>0]
[4, 4, 16]
>>> [v**2 if v%2 == 0 else v+1 for v in [2, 3, 4, -1] if v>0]
[4, 4, 16]
⑥列表推导式支持文件对象迭代
>>>fp = open('C:\install.log','r')
>>>print([line for line in fp])
>>>fp.close()
⑦ 使用列表推导式生成100以内的所有素数
>>> [p for p in range(2, 100) if 0 not in [p%d for d in range(2, int(p**0.5)+1)]]
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
2.1.9 使用列表实现向量运算
>>> import random
>>> x = [random.randint(1,100) for i in range(10)] #生成随机数
>>> list(map(lambda i: i+5, x)) #所有元素同时加5
>>> x = [random.randint(1,10) for i in range(10)]
>>> y = [random.randint(1,10) for i in range(10)]
>>> import operator
>>> sum(map(operator.mul, x, y)) #向量内积
>>> sum((i*j for i, j in zip(x, y))) #向量内积
>>> list(map(operator.add, x, y)) #两个等长的向量对应元素相加
PS:
本篇主要参考董付国老师的《Python可以这样学》一书,这是一本不错的Python入门书籍,有兴趣的可以买本看看,当然,也可以持续关注我的博客,我会一直更新相关内容的。