要点概论
1. 数组
1.1 列表和数组
python 语言中没有直接提供数组数据类型,通常使用列表作为数组。列表支持数组要求的 4 中核心操作:创建数组,索引访问,索引赋值,迭代遍历。
示例:生成一副扑克牌(大小王除外),并且随机洗牌后输出一副扑克牌。
import randomSUITS = ['Club','Diamind','Heart','Spade'] # 梅花,方块,红桃,黑桃RANKS = ['2','3','4','5','6','7','8','9','10','J','Q','K','A']deck = [] # 一副扑克牌for rank in RANKS: for suit in SUITS: card = rank + ' of ' + suit deck += [card]# 洗牌n = len(deck)for i in range(n): r = random.randrange(i,n) temp = deck[r] deck[r] = deck[i] deck[i] = temp# 输出一副扑克牌for s in deck: print(s) # 程序部分运行结果如下(结果每次随机):# 10 of Spade# 4 of Diamind# 3 of Heart# 5 of Spade# 5 of Heart# Q of Heart# 6 of Diamind# .....
1.2 array.array 对象和数组
array 模块包含一个array 对象,用于实现其他编程语言中的数组数据结构。
array 对象是包含相同基本数据类型的列表,其操作与 list 对象基本一致,区别是创建 array 对象时,必须指定其元素累心 typecode ,且其元素只能为该类型,否则会导致 TypeError。
array 对象构造函数为:
array(typecode[,initializer])
其中, typecode 为 array 对象中数据元素的类型; initializer 为初始化数据系列或可迭代对象,其元素类型必须与 typecode 一致。
array.array 对象和数组示例:
import arraya = array.array('b',(1,2,3,4,5))print(a[1]) # 2a[1] = 22print(a[1:]) # array('b', [22, 3, 4, 5])a[0] = 'abc' # TypeError: an integer is required (got type str)
2. 栈和队列
2.1 栈的实现:使用列表
向列表最后位置添加元素和移除元素非常高校和方便,故使用 list ,可以快捷高效地实现栈。 append() 和 pop() 分别对应入栈和出栈操作。
列表可以实现队列,但并不适合。因为从列表的头部移除一个元素,列表中的所有元素读需要移动位置,所以效率不高。
可以使用 collections 模块中的 deque 对象。
栈的实现示例【创建一个包含整数 1 和 2 的栈,展示入栈和出栈操作,以及打印栈的内容】:
class Stack: def __init__(self,size = 16): #初始化栈 self.stack = [] def push(self,obj): self.stack.append(obj) def pop(self): try: return self.stack.pop() except IndexError as e: print('stack is empty') def __str__(self): return str(self.stack)stack = Stack() # 创建并初始化栈stack.push(1) # 整数 1 入栈stack.push(2) # 整数 2 入栈print(stack) #打印栈的内容stack.pop() # 整数 2 出栈stack.pop() # 整数 1 出栈stack.pop() # 出栈操作,但因为是空栈,提示 'stack is empty'# 程序运行结果如下:# [1, 2]# stack is empty
2.2 deque 对象
colletions.deque (双端队列)支持从任意一端增加和删除元素。
deque 是线程安全,内存高校的队列,它被设计为从两端追加和弹出都非常快。
构造函数如下:
deque([iterable[,maxlen]]) # 构造函数
其中,可选的 iterable 为初始元素;maxlen 用于指定队列长度(默认无限制)。
deque 对象 dq 支持的方法如下表所示:
方法 | 说明 |
dq.append(x) | 在右端添加元素 x |
dq.appendleft(x) | 在左端添加元素 x |
dq.pop() | 从右端弹出元素。没有则抛出 IndexError |
dq.popleft() | 从左端弹出元素。没有则抛出 IndexError |
dq.extend(iterable) | 在右端添加系列 iterable 中的元素 |
dq.extendleft(iterable) | 在左端添加系列 iterable 中的元素 |
dq.remove(value) | 移除第一个找到的 x ,没有则抛出 IndexError |
dq.count() | 返回元素 x 在队列中出现的个数 |
dq.clear() | 删除所有元素,即清空队列 |
dq.reverse() | 反转队列中所有元素 |
dq.rotate(n) | 如果 n > 0 ,所有元素向右移动 n 个位置(循环);否则向左 |
deque 对象示例【读取文件,返回文件的最后 n 行内容】:
import collectionsdef tail(filename,n = 10): with open(filename) as f: return collections.deque(f,n)path = r'deque_tail.py'dq = tail(path,n = 2)print(dq.popleft())print(dq.popleft())# 程序运行结果如下:# print(dq.popleft())## print(dq.popleft())
2.3 deque 作为栈和队列
deque 对象方法 append() 用于入栈操作;pop() 方法对应于出栈操作。
deque 对象方法 append() 用于进队操作;popleft() 方法对应于出队操作。
deque 作为栈示例:
from collections import *dq = deque()dq.append(1);dq.append(2);dq.append(3) # 整数 1,2,3 入栈dq.pop();dq.pop();dq.pop() # 整数 3,2,1 出栈
deque 作为队列示例:
from collections import *dq = deque()dq.append(1);dq.append(2);dq.append(3) # 整数 1,2,3 入队dq.popleft();dq.popleft();dq.popleft() # 整数 3,2,1 出队
deque作为双向队列:
from collections import dequedq = deque(range(10),maxlen=10)print(dq)dq.rotate(3)# 队列的旋转操作接受一个参数 n ,当 n > 0 时,队列最右边的 n 个元素会被移动到队列的左边;# 当n < 0 时,队列最左边的 n 个元素会被移动到右边。print(dq)dq.appendleft(-1)# 当试图对一个已满(len(d) == d.maxlen)的队列做头部添加操作的时候,# 它尾部的元素会被删除掉。注意在下一行里,元素 6 被删除了。print(dq)dq.extend([11,22,33])# 在尾部添加三个元素的操作会挤掉 1-,7,8。print(dq)dq.extendleft([99,88,77])# extendleft(iter) 方法会把迭代器里的元素逐个添加到双向队列的左边,# 因此迭代器里的元素会逆序出现在队列中。print(dq)# 程序运行结果如下:# deque([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], maxlen=10)# deque([7, 8, 9, 0, 1, 2, 3, 4, 5, 6], maxlen=10)# deque([-1, 7, 8, 9, 0, 1, 2, 3, 4, 5], maxlen=10)# deque([9, 0, 1, 2, 3, 4, 5, 11, 22, 33], maxlen=10)# deque([77, 88, 99, 9, 0, 1, 2, 3, 4, 5], maxlen=10)
双向队列除了实现大部分列表所拥有的放啊,也有一些额外的符合自身设计的方法。
但是为了实现这些方法,双向队列也付出了一些代价,
从队列中间删除元素的操作会慢一些,因为它只对在头尾的操作进行了优化。
append 和 popleft 都是,也就是说 deque 可以在多线程程序中安全地当左先进先出的队列使用,
而使用者不需要担心资源所 的问题。
除了 deque 之外,还有其他的 python 标准库也有对队列的实现:
3. 集合
集合数据类型是没有顺序的简单对象的聚集,且集合中元素不重复。python 集合数据类型包括可变集合对象(set)和不可变集合对象(frozenset)。
3.1 集合的运算:并集,交集,差集和对称差集
集合运算如下表所示:
运算符 | 说明 |
s1|s2 ... | 返回 s1,s2,...的并集 |
s1&s2& ... | 返回 s1,s2,...的交集 |
s1-s2 | 返回 s1,s2,...的差集 |
s1^s2 | 返回 s1,s2, ...的对称差集 |
集合的对象方法如下表所示:
方法 | 说明 |
s1.isdisjoint(s2) | 如果集合 s1 和 s2 没有共同元素,返回 True ,否则返回 False |
s1.issubset(s2) | 如果集合 s1 是 s2 的子集,返回 True,否则返回 False |
s1.issuperset(s2) | 如果集合 s1 是 s2 的超集,返回 True,否则返回 False |
s1.union(s2, ...) | 返回 s1,s2,...的并集 |
s1.intersection(s2,...) | 返回 s1,s2,...的交集 |
s1.difference(s2,...) | 返回 s1,s2,...的差集 |
s1.symmetric_difference(s2) | 返回 s1 和 s2 的对称差集 |
3.2 集合的比较运算;相等,子集和超集
集合支持如下表所示的比较运算:
运算符 | 说明 | 运算符 | 说明 |
s1 = s2 | s1和 s2的元素相同 | s1 <= s2 | s1是 s2的子集 |
s1 != s2 | s1和 s2的元素不完全相同 | s1 >= s2 | s1是 s2的超集 |
s1 < s2 | s1是 s2的纯子集 | s1 > s2 | s1是 s2的纯超集 |
3.3 集合的长度,最大值,最小值,元素和
通过内置函数 len(), max(), min(), sum(),可以获取集合的长度,元素最小值,元素最小值,元素之和。
如果元素有非整数,则求和将导致 TypeError 异常。
4. 字典(映射)
字典(dict , 或映射 map)是一组键/值队的数据结构。每个键对应于一个值。在字典中,键不能重复。根据键可以查询到值。
4.1 对象的哈希值
字典是键和值的映射关系。字典的键必须是可 hash 的对象,即实现了 __hash__() 的对象,
一个对象的 hash 值也可以使用内置函数 hash() 获得。
不可变对象是可 hash 对象;而可变对象通常是不可 hash 对象,因为不可变对象的内容可以改变,因而无法通过 hash() 函数获取其 hash 值。
字典的键只能使用不可变的对象,但字典的值可以使用不可变或可变的对象。一般而言,应该使用简单的对象作为键。
4.2 字典的视图对象
字典 d 支持下列的视图对象,通过它们,可以动态访问字典中的数据。
d.key() # 返回字典 d 的键 key 的列表
d.values() # 返回字典 d 的值 value 的列表
d.items() # 返回字典 d 的键值(key ,value)队的列表
4.3 字典对象的长度和比较
通过内置函数 len(),可以获取字典的长度(元素个数)。
虽然字典对象也支持内置函数 max() ,min() ,sum(),以计算字典 key,但没有太大意义。
另外,字典对象也支持比较运算符(< ,<= ,== ,!= ,>= ,>),但只有 == ,!= 有意义。
5.collections 数据结构简介