知识点
简单的来说,数据结构(data structure)是计算机中存储、组织数据的方式,可以参考 Wikipedia 。Python 有许多内建的数据结构,列表就是一种数据结构。
- 列表的方法与列表元素的删除
- 将列表用作栈和队列
- 列表推导式
- 元组、集合、字典的创建与操作
- enumerate() 和 zip() 函数
列表
首先建立了一个列表 a。
>>> a = [23, 45, 1, -3434, 43624356, 234]
调用列表的方法 a.append(x) 添加元素 x 到列表末尾。
>>> a.append(45)
>>> a
[23, 45, 1, -3434, 43624356, 234, 45]
使用列表的 insert(x, pos) 方法将数据插入到列表的任何位置 pos 。
>>> a.insert(0, 1) # 在列表索引 0 位置添加元素 1
>>> a
[1, 23, 45, 1, -3434, 43624356, 234, 45]
>>> a.insert(0, 111) # 在列表索引 0 位置添加元素 111
>>> a
[111, 1, 23, 45, 1, -3434, 43624356, 234, 45]
列表方法 count(x) 会返回列表元素中 x 的数目。
>>> a.count(45) # 查找元素 45 在列表中出现的次数
2
使用 remove(x) 方法在列表中移除首次出现的元素 x 。
>>> a.remove(234)
>>> a
[111, 1, 23, 45, 1, -3434, 43624356, 45]
反转整个列表。
>>> a.reverse()
>>> a
[45, 43624356, -3434, 1, 45, 23, 1, 111]
使用列表的 extend(list) 方法将一个列表的所有元素添加到另一个列表的末尾。
>>> b = [45, 56, 90]
>>> a.extend(b) # 添加 b 的元素而不是 b 本身
>>> a
[45, 43624356, -3434, 1, 45, 23, 1, 111, 45, 56, 90]
使用列表的 sort() 方法给列表排序,排序的前提是列表的元素是可比较的。
>>> a.sort()
>>> a
[-3434, 1, 1, 23, 45, 45, 45, 56, 90, 111, 43624356]
使用 del 关键字删除指定位置的列表元素。
>>> del a[-1]
>>> a
[-3434, 1, 1, 23, 45, 45, 45, 56, 90, 111]
将列表用作栈和队列
栈是一种 LIFO (Last In First Out 后进先出)数据结构,可以用列表模拟。
append(x) 方法可在列表末尾追加元素 x ,pop() 方法可以移除列表最后一个元素 x 并返回。
>>> a = [1, 2, 3, 4, 5, 6]
>>> a
[1, 2, 3, 4, 5, 6]
>>> a.pop()
6
>>> a.pop()
5
>>> a.pop()
4
>>> a.pop()
3
>>> a
[1, 2]
>>> a.append(34)
>>> a
[1, 2, 34]
队列与栈不同,它是 FIFO (First In First Out 先进先出)的数据结构,也可以用列表模拟。
append(x) 方法可在列表末尾追加元素 x 。pop(0) 方法可以指定移除列表中第一个元素并返回。方法 pop(i) 可以指定移除列表中第 i 个元素并返回。
>>> a = [1, 2, 3, 4, 5]
>>> a.append(1)
>>> a
[1, 2, 3, 4, 5, 1]
>>> a.pop(0)
1
>>> a.pop(0)
2
>>> a
[3, 4, 5, 1]
列表推导式
一般都是通过将一些操作应用于序列的每个成员并通过返回的元素创建列表,或者通过满足特定条件的元素创建子序列。
列表推导式为从序列中创建列表提供了一个简单的方法。
>>> # 创建一个 squares 列表
>>> squares = []
>>> for x in range(10):
... squares.append(x ** 2)
...
>>> squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
注意这个 for 循环中的被创建(或被重写)的名为 x 的变量在循环完毕后依然存在。
使用如下方法,可以计算 squares 的值而不会产生任何的副作用。
squares = list(map(lambda x : x ** 2, range(10)))
# 等价于下面的列表推导式。
squares = [x ** 2 for x in range(10)]
列表推导式由包含一个表达式的中括号组成,表达式后面跟随一个 for 子句,之后可以有零或多个 for 或 if 子句。结果是一个列表,由表达式依据其后面的 for 和 if 子句上下文计算而来的结果构成。
列表推导式结合两个列表的元素,如果元素之间不相等的话。
>>> [(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)]
>>>
>>> # 等同于
>>>
>>> combs = []
>>> for x in [1,2,3]:
... for y in [3,1,4]:
... if x != y:
... combs.append((x, y))
...
>>> combs
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
列表推导式也可以嵌套使用。
>>> a = [1,2,3]
>>> z = [x + 1 for x in [x ** 2 for x in a]]
>>> z
[2, 5, 10]
元组
元组是由数个逗号分割的值组成。
>>> a = 'C', 'C++', 'Java', 'Python'
>>> a
('C', 'C++', 'Java', 'Python')
>>> a[3]
'Python'
>>> for x in a :
... print(x, end = ' ')
...
C C++ Java Python
可以对任何一个元组执行拆封操作并赋值给多个变量。
>>> divmod(15,2) # divmod.__doc__ ==> Return the tuple (x//y, x%y)
(7, 1)
>>> x, y = divmod(15,2)
>>> x
7
>>> y
1
元组是不可变类型,不能在元组内删除或添加或编辑任何值。如果尝试这些操作,将会出错。
>>> a = (1, 2, 3, 4)
>>> del a[0] # 删除元素
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object doesn't support item deletion
要创建只含有一个元素的元组,必须在值后面跟一个逗号。
>>> a = (123)
>>> a
123
>>> type(a)
<class 'int'>
>>> a = (123, )
>>> b = 321,
>>> a
(123,)
>>> b
(321,)
>>> type(a)
<class 'tuple'>
>>> type(b)
<class 'tuple'>
通过内建函数 type() 可以显示任何对象的数据类型。
使用 len() 函数来查询任意序列类型数据的长度。
>>> a = (123, )
>>> a
(123,)
>>> len(a)
1
>>> type(len)
<class 'builtin_function_or_method'>
集合
集合是一个无序不重复元素的集。基本功能包括关系测试和消除重复元素。
集合对象还支持 union(联合),intersection(交),difference(差)和 symmetric difference(对称差集)等数学运算。
大括号或 set() 函数可以用来创建集合。注意,创建空集合必须使用 set() 而不是 {} ,后者用于创建空字典。
下面是集合的常见操作:
>>> basket = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}
>>> print(basket) # 可以看到重复的元素被去除
{'orange', 'banana', 'pear', 'apple'}
>>> 'orange' in basket
True
>>> 'crabgrass' in basket
False
>>> # 演示对两个单词中的字母进行集合操作
...
>>> a = set('abracadabra')
>>> b = set('alacazam')
>>> a # a 去重后的字母
{'a', 'r', 'b', 'c', 'd'}
>>> a - b # a 有而 b 没有的字母
{'r', 'd', 'b'}
>>> a | b # 存在于 a 或 b 的字母
{'a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'}
>>> a & b # a 和 b 都有的字母
{'a', 'c'}
>>> a ^ b # 存在于 a 或 b 但不同时存在的字母
{'r', 'd', 'b', 'm', 'z', 'l'}
>>> # 从集合中添加或弹出元素
>>> a = {'a','e','h','g'}
>>> a.pop() # pop 方法随机删除一个元素并打印
'h'
>>> a.add('c')
>>> a
{'c', 'e', 'g', 'a'}
字典
字典是是无序的键值对(key:value)集合,同一个字典内的键必须是互不相同的。
一对大括号 {} 创建一个空字典。初始化字典时,在大括号内放置一组逗号分隔的键 : 值对
,这也是字典输出的方式。
使用键来检索存储在字典中的数据。
>>> data = {'kushal':'Fedora', 'kart_':'Debian', 'Jace':'Mac'}
>>> data
{'kushal': 'Fedora', 'Jace': 'Mac', 'kart_': 'Debian'}
>>> data['kart_']
'Debian'
创建新的键值对很简单:
>>> data['parthan'] = 'Ubuntu'
>>> data
{'kushal': 'Fedora', 'Jace': 'Mac', 'kart_': 'Debian', 'parthan': 'Ubuntu'}
使用 del 关键字删除任意指定的键值对:
>>> del data['kushal']
>>> data
{'Jace': 'Mac', 'kart_': 'Debian', 'parthan': 'Ubuntu'
使用 in 关键字查询指定的键是否存在于字典中。
>>> 'ShiYanLou' in data
False
字典中的键必须是不可变类型,不能使用列表作为键。
dict() 可以从包含键值对的元组中创建字典。
>>> dict((('Indian','Delhi'),('Bangladesh','Dhaka')))
{'Indian': 'Delhi', 'Bangladesh': 'Dhaka'}
如果你想要遍历一个字典,使用字典的 items() 方法。
>>> data
{'Kushal': 'Fedora', 'Jace': 'Mac', 'kart_': 'Debian', 'parthan': 'Ubuntu'}
>>> for x, y in data.items():
... print("{} uses {}".format(x, y))
...
Kushal uses Fedora
Jace uses Mac
kart_ uses Debian
parthan uses Ubuntu
往字典中的元素添加数据时,首先要判断这个元素是否存在,不存在则创建一个默认值。如果在循环里执行这个操作,每次迭代都需要判断一次,降低程序性能。
可以使用 dict.setdefault(key, default) 更有效率的完成这个事情。
>>> data = {}
>>> data.setdefault('names', []).append('Ruby')
>>> data
{'names': ['Ruby']}
>>> data.setdefault('names', []).append('Python')
>>> data
{'names': ['Ruby', 'Python']}
>>> data.setdefault('names', []).append('C')
>>> data
{'names': ['Ruby', 'Python', 'C']}
试图索引一个不存在的键将会抛出一个 keyError 错误。
可以使用 dict.get(key, default) 来索引键,如果键不存在,那么返回指定的 default 值。
>>> data['foo']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'foo'
>>> data.get('foo', 0)
0
使用 enumerate() 在遍历列表(或任何序列类型)的同时获得元素索引值。
>>> for i, j in enumerate(['a', 'b', 'c']):
... print(i, j)
...
0 a
1 b
2 c
使用 zip() 函数同时遍历两个序列类型。
>>> a = ['Pradeepto', 'Kushal']
>>> b = ['OpenSUSE', 'Fedora']
>>> for x, y in zip(a, b):
... print("{} uses {}".format(x, y))
...
Pradeepto uses OpenSUSE
Kushal uses Fedora
总结
在写程序的过程中,不同的场景应当选取合适的数据结构。
除了以上几种 Python 内置的常用数据结构,Python 中还有一些其它有用的数据结构,可以在这里了解。