昨天简单的介绍了一下Python中常用的一些内建(build-in)的数据结构,今天举一些具体的例子,并对这些数据结构的API做一个简单的说明。

list

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# 初始化空list,也可以是 a = []
a = list() # a = []
# 也可以直接初始化一个含有元素的list
a = [1,2,3] # a = [1,2,3]
# list尾部添加一个元素
a.append(5) # a = [1,2,3,5]
# 一次性在list尾部添加多个元素
a.extend([7,1,2]) # a = [1,2,3,5,7,1,2]
# 计算该list中某个元素有多少个
a.count(1) # 返回2
# 返回元素的指标index
a.index(7) # 返回4,元素重复则头一个
# 指定位置插入新的元素
# 第一个变量是位置,第二个是插入元素值
a.insert(3,6) # a = [1,2,3,6,5,7,1,2]
# 删除元素
a.remove(7) # a = [1,2,3,6,5,1,2]
# 返回指定位置元素值并删除
a.pop(1) # a = [1,2,3,6,5,1,2] 返回2
# 翻转list
a.reverse() # a = [2,1,5,6,3,1]
# 排序
a.sort() # a = [1,1,2,3,5,6]
# 复制操作
b = a.copy()
# 一次访问多个元素
a[1:4] # 输出 [1,2,3]
a[3:] # 输出 [3,5,6]
a[1:6:2] # 输出 [1,3,6]
a[5::-2] # 输出 [6,3,1]
# 还可以用负指标
# a[-1]对应最后一个元素,以此类推
a[:-3] # 输出 [1,1,2]
# 清空元素
a.clear() # a = []
# 其他
['2']*5 # ['2', '2', '2', '2', '2']

复制操作需要特别说明一下,这里备份list不能直接用等号,而要调用copy方法进行,不然仅仅是引用,内存地址不会发生变化,
例如若b = a,改变b中元素的值,a中的对应位置的值也会发生变化。甚至切片方式(括号[]中1:6:2就是一种切片)赋值也是不行的。
另外在Python中这些数据类型指标index都是从0开始的,这里类此C/C++。

tuple

tuple中只有两个方法count和index并和list中的用法相同,这里不再赘述。但是tuple可以有一些其他的用途。

1
2
3
4
5
6
7
8
9
10
# 交换两个元素的值
x, y = y, x
# 这里更完整一些其实就是
(x, y) = (y, x)
# 相当于用一个tuple给另一个tuple进行赋值
# 一般的编程语言中都需要中间变量
# list和tuple相互转换
a = [1,2] # a = [1,2]
b = tuple(a) # b = (1,2)
c = list(b) # c = [1,2]

需要注意的是在定义一个元素的tuple的时候,需要加上一个逗号在后面。

1
2
a = 1,    # a = (1,)
b = (1) # b = 1

前者定义了一个单元素元组,后者仅仅是一个变量,因为后者中的括号只是为了限定算数运算顺序而加的,这里特别需要注意。
另外tuple是有序的,即(1,2)和(2,1)不等价(两者的hash值不同)。

dict

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 初始化空字典,也可以用a = {}
a = dict() # a = {}
# 也可以直接初始化含有元素的字典
# 指标可以为数字和字符串
a = {1:'a', 'b':'c'} # a = {1: 'a', 'b':'c'}
# 添加一个新元素
a['z'] = 'y' # a = {1: 'a', 'b':'c', 'z':'y'}
# 通过键key得到值value,两种方式
a.get('z') # 输出'y'
a['z'] # 输出'y'
# 更新元素的两种方法
a.update({'z':'x'})
a['z'] = 'x' # a = {1: 'a', 'b':'c', 'z':'x'}
# 得到dict所有的键
a.keys() # dict_keys([1, 'b', 'z'])
# 得到dict所有的值
a.values() # dict_values(['a', 'c', 'y'])
# setdefault,key值存在则输出对应value
# 否则输出后面的默认值,并添加到dict中
a.setdefault(2,'g') # 输出g,默认为None
# popitem返回最后一个键和值并删除
a.popitem() # 返回 {2:'g'}
# 新建一个相同keys的dict,默认元素值为None
b = {} # 这里必须先初始化
b.fromkeys(a, 'c') # b = {1:'c','b':'c',2:'c'}
# pop、clear、copy和list中的类似
# 不过这里不是index而是key
# 最后一个items是dict的迭代器
for key, val in a.items():
print(key, val)

dict是利用hashmap实现,从而查找键值的速度很快,另外需要注意的是dict是一种无序的字典,在collections中的OrderedDict是有序字典。

推荐LeetCode中的第1题两数之和练习一下,利用dict会使得程序运行速度快很多。

set

set为不含有重复元素的集合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 初始化空集合
a = set()
# 注意这里不能用a = {}初始化
# 因为这种方式初始化的是空dict
# 也可以初始化一个非空的set
a = {1,2,3,1} # a = {1,2,3}
# 添加元素到set中
a.add(4) # a = {1,2,3,4}
# 移除元素
a.remove(2) # a = {1,3,4}
# 集合运算 并和交
b = {3,4,5,6}
a & b # 输出{3,4}
a | b # 输出{1,3,4,5,6}

set的API有点多,而且大多从名字上就能看出是用来做什么的,这里不再赘述。
另外类似类似set的Counter可以保留元素的个数信息,也需要通过collections导入。

推荐LeetCode中的第349和350题,两个数组的交集。

写在最后:

关于在循环中如何迭代这些数据类型,将在下一次进行说明。

有zip、enumerate以及itertools中的各种迭代器。利用这些语句可以使得循环遍历变得方便。