5 Python常用数据结构
Table of Contents
1 List
1.1 List 的使用
- List 相关函数:append,extend,insert,remove,pop,index,count,sort,reverse
>>> a[3, 1, 2]>>> b[4, 7, 6, 10]>>> a.append(5)>>> a[3, 1, 2, 5]>>> a.extend(b)>>> a[3, 1, 2, 5, 4, 7, 6, 10]>>> a.insert(0,9)>>> a[9, 3, 1, 2, 5, 4, 7, 6, 10]>>> a.insert(1,8)>>> a[9, 8, 3, 1, 2, 5, 4, 7, 6, 10]>>> a.insert(5,1)>>> a[9, 8, 3, 1, 2, 1, 5, 4, 7, 6, 10]>>> a.remove(1)>>> a[9, 8, 3, 2, 1, 5, 4, 7, 6, 10]>>> a.pop(0)9>>> a[8, 3, 2, 1, 5, 4, 7, 6, 10]>>> a.pop()10>>> a[8, 3, 2, 1, 5, 4, 7, 6]>>> a.index(1)3>>> a.insert(2,6)>>> a[8, 3, 6, 2, 1, 5, 4, 7, 6] >>> a.count(3)1>>> a.count(6)2>>> a.sort()>>> a[1, 2, 3, 4, 5, 6, 6, 7, 8]>>> a.reverse()>>> a[8, 7, 6, 6, 5, 4, 3, 2, 1]>>>
1.2 将List当作栈(Stack)
使用上面将的 append, pop 函数很容易将List当作栈来使用。栈有先进后出的特点。
>>> stack = [5,2,8]>>> stack.append(9)>>> stack[5, 2, 8, 9]>>> stack.append(1)>>> stack[5, 2, 8, 9, 1]>>> stack.pop()1>>> stack[5, 2, 8, 9]>>> stack.pop()9>>> stack[5, 2, 8]
1.3 将List当作队列
List同样很容易当作队列来使用,队列的特点是先进先出。然而,这样使用效率非常低。因为在队列头部删除元素时, 所有后面的元素都要左移。 可以使用collections.deque来实现队列,它是专门用于队列的,其设计保证了入队和出队的效率。
>>> from collections import deque>>> queue = deque(["Linux","Unix","Windows"])>>> queuedeque(['Linux', 'Unix', 'Windows'])>>> queue.append("Mac")>>> queuedeque(['Linux', 'Unix', 'Windows', 'Mac'])>>> queue.popleft()'Linux'>>> queuedeque(['Unix', 'Windows', 'Mac'])
1.4 函数式程序设计工具
对于List来说,有三个函数是非常有用的:filter,map,reduce
- filter(function,sequence) 从序列中选出能使函数function返回真的元素
>>> def f(x): return x % 2 !=0 and x % 3 != 0... >>> filter(f, range(1,20))[1, 5, 7, 11, 13, 17, 19]
- map(function,sequence) 将函数function作用到sequence上的每一个元素,返回对应的值
>>> def f(x): return x*2+1... >>> map(f,range(1,10))[3, 5, 7, 9, 11, 13, 15, 17, 19]
如果函数有两个参数,那么需要两个序列
>>> def f(x,y): return x + y... >>> map(f,[1,5,2],[6,3,9])[7, 8, 11]
- reduce(function,sequence) 将二元函数function作用在sequence前两个元素上,再将结果和下一个元素共同作为函数参数
>>> def f (x,y): return x + y... >>> reduce(f,[1,2,3,4])10>>> def f(x,y): return x*y... >>> reduce(f,[1,2,3,4])24
1.5 List Comprehensions
List Comprehensions 是创建List的一种方式,例如
>>> squares = [x**2 for x in [4,3,7]]>>> squares[16, 9, 49]>>> [(x,y) for x in [1,2,3] for y in [3,2,4] if x != y][(1, 3), (1, 2), (1, 4), (2, 3), (2, 4), (3, 2), (3, 4)]
这种方式有时候可以避免写很多代码,而且清晰可读,和数学里定义集合的方式很像,haskell中也有这样的方式。 另外,这货还可以嵌套着玩儿
>>> matrix = [... [1,2,3,4],... [5,6,7],... [8,9,10,11,12]... ]>>> matrix[[1, 2, 3, 4], [5, 6, 7], [8, 9, 10, 11, 12]]>>> [ [row[i] for row in matrix] for i in range(3) ][[1, 5, 8], [2, 6, 9], [3, 7, 10]]
当然,这只是体现List Comprehensions的特性,真玩的时候,我们还有更方便的:
>>> zip(*matrix)[(1, 5, 8), (2, 6, 9), (3, 7, 10)]
2 del 语句
>>> a = [5,2,67,1,72,1,728]>>> a[5, 2, 67, 1, 72, 1, 728]>>> del a[0]>>> a[2, 67, 1, 72, 1, 728]>>> del a[1:3]>>> a[2, 72, 1, 728]>>> del a[:]>>> a[]>>> del a>>> aTraceback (most recent call last): File "", line 1, in NameError: name 'a' is not defined
3 Tuples 和 序列
表示序列的,还有一种标准的数据结构,Tuples。 Tuple中的元素是不能修改的。 虽然Tuple和List看起来很像,但是他们用于不同的场合,后面我们会介绍。
>>> t = "linux", "unix", "winx">>> t('linux', 'unix', 'winx')>>> p = ("ubuntu","arch","freebsd")>>> p('ubuntu', 'arch', 'freebsd')>>> t[0]'linux'>>> t[0] = "*nix"Traceback (most recent call last): File "", line 1, in TypeError: 'tuple' object does not support item assignment>>> s = [1,2,3]>>> s[1, 2, 3]>>> s[0] = 9>>> s[9, 2, 3]
Tuple 有packing 和 unpacking 两个概念 packing 就是:
>>> t = "linux","unix","freebsd"
unpacking 就是:
>>> x, y, z = t>>> x'linux'>>> y'unix'>>> z'freebsd'
4 Sets
python还有一种数据结构,Sets。用于存放不重复元素的无序集合,常用于成员测试,消除重复项等。Sets支持 数学集合中的交,差,并,等操作。
>>> os = ['linux','windows7','freebsd']>>> oset = set(os)>>> osetset(['windows7', 'freebsd', 'linux'])>>> 'linux' in osetTrue>>> 'unix' in osetFalse>>> a = set('sdkf;ahdf')>>> b = set('safj13325er')>>> a - b # 在 a 不在 bset(['h', 'k', 'd', ';'])>>> a | b # 在 a 或在 bset(['r', 'a', 'e', 'd', 'f', 'h', 'k', 'j', '3', '1', 's', '2', '5', ';'])>>> a & b # 在 a 且在 bset(['a', 's', 'f'])>>> a ^ b # 在 a 或在 b 且不同时在a,bset(['e', 'd', 'h', 'k', 'j', '1', '3', '2', '5', ';', 'r'])
集合也支持 comprehensions 特性
>>> a = {x for x in 'abcde' if x not in 'abe'}>>> aset(['c', 'd'])
但是,必须要注意,定义一个sets时不能用{},而要用set()
5 Dictionaries
Python中另一个有用的数据结构是Dictionary。它由key:value两部分组成,通过key值可以查找到value,key值是惟一的。
>>> tel = { 'jack':123, 'lucy':456}>>> tel['lucy']456>>> tel{ 'jack': 123, 'lucy': 456}>>> tel['lily'] = 789>>> tel{ 'lily': 789, 'jack': 123, 'lucy': 456}>>> tel.keys()['lily', 'jack', 'lucy']>>> 'lily' in telTrue
使用dict可以由(key,value)组成的序列直接构造dictionary. 使用comprehension的方式也可以构造dictionary.
>>> dict( [('linux',123),('unix',456)] ){ 'unix': 456, 'linux': 123}>>> dict(linux=826, unix=910){ 'unix': 910, 'linux': 826}>>> {x: x*2+1 for x in (3,7,1)}{1: 3, 3: 7, 7: 15}
6 循环技术
当我们想遍历一个序列时,可以使用 下标,值,enumerate() 来完成
>>> for i, v in enumerate(['linux', 'unix', 'winx']):... print i, v... 0 linux1 unix2 winx
当我们想遍历两个及以上序列时,可以用 zip() 来完成
>>> ask = ['name', 'system', 'editor']>>> answer = ['Steve', 'Mac', 'emacs']>>> for q, a in zip(ask, answer):... print 'What is your {0}? It is {1}.'.format(q,a)... What is your name? It is Steve.What is your system? It is Mac.What is your editor? It is emacs.
如果想逆序遍历,可以用 reversed() 来完成
>>> for i in reversed(['winx', 'unix', 'linux']):... print i... linuxunixwinx
如果想排序后再遍历,可以用 sorted() 来完成
>>> for i in sorted( ['unix', 'linux', 'winx'] ):... print i... linuxunixwinx
如果想遍历一个dictionary,可以用iteritems()来完成
>>> system = { 'unix':'second', 'linux':'first', 'winx':'last' }>>> for key,value in system.iteritems():... print key, value... unix secondwinx lastlinux first
7 更多的条件操作
对于 while 和 if 而言,条件操作不仅仅是比较,还有更多可用操作。 in 和 not in 可以判断一个元素是否在一个序列中 is 和 not is 可以判断两个对象是不是指的是同一个对象 比较操作可以链接起来,例如 a < b == c , 表示 a < b 且 b == c 还有著名Bool操作: and, or, not ,它们可以配合比较操作 Bool操作优先级低于比较操作,其中not优先级最高,or最低
8 比较序列操作
序列对象也可以比较,它们是按照 字典序(lexicographical ordering) 的顺序比较
>>> (1,2,3) < (1,2,4)True>>> (1,2,3,4) < (1,2,3)False>>> (1,2,3,-1) < (1,2,3)False>>> (1,2,3) == (1.0,2.0,3.0)True