5.数据结构

5.1 列表的更多特性

5.1.2 列表作为队列使用

列表作为栈使用很方便,但作为队列使用时相当低效,一般使用collections.deque实现队列

1
from collections import deque
1
2
3
4
queue = deque(["Eric", "John", "Michael"])
queue.append("Terry") # Terry arrives
queue.append("Graham") # Graham arrives
print(queue)
deque(['Eric', 'John', 'Michael', 'Terry', 'Graham'])
1
queue.popleft() # The first to arrive now leaves
'Eric'
1
print(queue)
deque(['John', 'Michael', 'Terry', 'Graham'])
1
queue.popleft() # The second to arrive now leaves
'John'
1
print(queue) # Remaining queue in order of arrival
deque(['Michael', 'Terry', 'Graham'])

5.1.3 列表推导式

1
2
squares = list(map(lambda x: x**2, range(10)))
print(squares)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
1
2
squares = [x**2 for x in range(10)]
print(squares)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
1
[(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)]

5.1.4 嵌套的列表推导式

1
2
3
4
matrix = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]]
1
2
# 下面的列表推导式将交换其行和列
[[row[i] for row in matrix] for i in range(4)]
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
1
[row[i] for row in matrix for i in range(4)]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
1
[row[i] for i in range(4) for row in matrix]
[1, 5, 9, 2, 6, 10, 3, 7, 11, 4, 8, 12]
1
[[row[i] for i in range(4)] for row in matrix]
[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]

5.2 del语句

1
a = [1,2,3]
1
del a[0]
1
a
[2, 3]
1
del a[:]
1
a
[]
1
del a
1
a
---------------------------------------------------------------------------

NameError                                 Traceback (most recent call last)

<ipython-input-49-3f786850e387> in <module>
----> 1 a


NameError: name 'a' is not defined

5.3 元组和序列

  1. 元组可以嵌套
  2. 元组创建后不可修改(元组中的列表可以修改)
  3. 元组可以包含多个对象
  4. 输入时圆括号可有可无,不过经常会是必须的(如果这个元组是一个更大的表达式的一部分)
  5. 给元组中的一个单独的元素赋值是不允许的,当然你可以创建包含可变对象的元组,例如列表。
1
t = (1,2,3),[1,2,3]
1
t[1][0] = 0
1
t
((1, 2, 3), [0, 2, 3])
1
t[0][0] = 0
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-57-7426bf581dcb> in <module>
----> 1 t[0][0] = 0


TypeError: 'tuple' object does not support item assignment
1
2
empty = ()  # 空元组
print(type(empty))
<class 'tuple'>
1
2
singleton = ('hello',) # 只包含一个元素的元组
print(type(singleton))
<class 'tuple'>

虽然元组可能看起来与列表很像,但它们通常是在不同的场景被使用,并且有着不同的用途。

元组是immutable ,其序列通常包含不同种类的元素,并且通过解包(这一节下面会解释)或者索引来访问
(如果是namedtuples 的话甚至还可以通过属性访问)。

列表是mutable ,并且列表中的元素一般是同种类型的,并且通过迭代访问。

1
2
3
4
5
# 元组打包和解包
t = 12345, 54321, 'hello!'
print('t = ', t)
x, y, z = t
print('x = {0}, y = {1}, z = {2}'.format(x, y, z))
t =  (12345, 54321, 'hello!')
x = 12345, y = 54321, z = hello!

5.4 集合

集合是由不重复元素组成的无序的集。它的基本用法包括成员检测和消除重复元素。集合对象也支持像联合,交集,差集,对称差分等数学运算。

花括号或set() 函数可以用来创建集合。注意:要创建一个空集合你只能用set() 而不能用{},因为后者是创建一个空字典

1
basket = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}
1
2
a = set('abracadabra')
b = set('alacazam')
1
2
print(a)
print(b)
{'c', 'b', 'r', 'a', 'd'}
{'c', 'l', 'z', 'm', 'a'}
1
a - b
{'b', 'd', 'r'}
1
a | b
{'a', 'b', 'c', 'd', 'l', 'm', 'r', 'z'}
1
a & b
{'a', 'c'}
1
a ^ b
{'b', 'd', 'l', 'm', 'r', 'z'}
1
2
3
# 推导形式
a = {x for x in 'abracadabra' if x not in 'abc'}
print(a)
{'r', 'd'}

5.5 字典

字典是以关键字为索引的,关键字可以是任意不可变类型,通常是字符串或数字。

理解字典的最好方式,就是将它看做是一个键: 值对的集合,键必须是唯一的(在一个字典中)。一对花括号可以创建一个空字典:{}

字典主要的操作是使用关键字存储和解析值。也可以用del 来删除一个键值对。

对一个字典执行list(d) 将返回包含该字典中所有键的列表,按插入次序排列(如需其他排序,则要使用sorted(d))。

要检查字典中是否存在一个特定键,可使用in 关键字。

1
2
# dict()构造函数可以直接从键值对序列里创造字典
dict([('space', 4193), ('guido', 4127), ('jack', 4098)])
{'space': 4193, 'guido': 4127, 'jack': 4098}
1

1
2
# 字典推导式可以从任意的键值表达式中创建字典
{x: x**2 for x in (2, 4, 6)}
{2: 4, 4: 16, 6: 36}
1
2
# 当关键字是简单字符串时,有时直接通过关键字参数来指定键值对更方便
dict(space=4193, guido=4172, jack=4098)
{'space': 4193, 'guido': 4172, 'jack': 4098}

5.6 循环的技巧

当在字典中循环时,用items() 方法可将关键字和对应的值同时取出;

当在序列中循环时,用enumerate() 函数可以将索引位置和其对应的值同时取出;

1
2
3
4
5
# 当同时在两个或更多序列中循环时,可以用zip() 函数将其内元素一一匹配。
questions = ['name', 'quest', 'favorite color']
answers = ['lancelot', 'the holy grail', 'blue']
for q, a in zip(questions, answers):
print('What is your {0}? Itis {1}.'.format(q, a))
What is your name? Itis lancelot.
What is your quest? Itis the holy grail.
What is your favorite color? Itis blue.
1
2
3
# 如果要逆向循环一个序列,可以先正向定位序列,然后调用reversed() 函数
for i in reversed(range(1, 10, 2)):
print(i)
9
7
5
3
1
1
2
3
4
# 如果要按某个指定顺序循环一个序列,可以用sorted() 函数,它可以在不改动原序列的基础上返回一个新的排好序的序列
basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
for f in sorted(set(basket)):
print(f)
apple
banana
orange
pear
1
2
3
4
5
6
7
8
# 有时可能会想在循环时修改列表内容,一般来说改为创建一个新列表是比较简单且安全的
import math
raw_data = [56.2, float('NaN'), 51.7, 55.3, 52.5, float('NaN'), 47.8]
filtered_data = []
for value in raw_data:
if not math.isnan(value):
filtered_data.append(value)
print(filtered_data)
[56.2, 51.7, 55.3, 52.5, 47.8]

5.7 深入条件控制

5.8 比较序列和其他类型