Python 中的数据结构
“数据结构”这个词大家肯定都不陌生,高级程序语言有两个核心,一个是算法,另一个就是数据结构。不管是c语言系列中的数组、链表、树和图,还是java中的各种map,随便抽出一个就可以虐我们千万遍。
Python作为高级程序语言的一种,它的数据结构即继承了传统数据结构的本职工作,又提高了办事效率,可谓青出于蓝而胜于蓝。免去了繁琐的指针操作,使用起来真是神清气爽吖!
好啦,下面就切入正题吧~
Python中常见的数据结构可以统称为容器(container)。其中序列(如列表和元组)、映射(如字典)以及集合(set)是三类主要的容器。欲知详情,请接着看~
一、序列sequence
序列中的每个元素都有自己的编号。Python中有6种内建的序列。其中列表和元组是最常见的类型。其他包括字符串、Unicode字符串、buffer对象和xrange对象
重点说说列表、元组和字符串这三位。
1.1 列表list
列表区别于字符串和元组的最重要的特点是:列表可以修改,而字符串和元组不能。
a) list创建
list的创建非常类似于js中的数组~比如:
若输入:
1 list1=['hello','world']
2 print list1
3 list2=[1,2,3]
4 print list2
则输出:
1 ['hello', 'world']
2 [1, 2, 3]
b) list函数
list函数(其实list是一种类型而不是函数)对字符串创建列表是非常有效的,比如下面:
若输入
1 list3=list("hello")
2 print list3
则输出:
1 ['h', 'e', 'l', 'l', 'o']
1.2 元组tuple
元组与列表一样也是一种序列,唯一不同的是元组不能被修改(其实字符串也有这个特点的)。
a) tuple创建
若输入
1 t1=1,2,1
2 t2="sinaWeibo","liuxiaoyan"
3 t3=(1,2,3,4)
4 t4=()
5 t5=(1,)
6 print t1,t2,t3,t4,t5
输出:
1 (1, 2, 1) ('sinaWeibo', 'liuxiaoyan') (1, 2, 3, 4) () (1,)
所以可以看出一些端倪:
- a、逗号分隔一些值,元组自动创建完成
- b、元组大部分时候是通过圆括号括起来的
- c、空元组可以用没有包含内容的圆括号来表示
- d、只含一个值的元组,必须加个逗号(,)
b) tuple函数
tuple函数和序列的list函数几乎一样:以一个序列(注意是序列)作为参数并把它转换为元组。
如果参数就算元组,那么该参数就会原样返回:
若输入:
1 t1=tuple([1,2,3])
2 t2=tuple("sina")
3 t3=tuple((1,2,3))
4 print t1
5 print t2
6 print t3
则输出:
1 (1, 2, 3)
2 ('s', 'i', 'n', 'a')
3 (1, 2, 3)
1.3 字符串string
a) string创建
若输入
1 str1='Hello Sina'
2 print str1
3 print str1
4 for c in str1:
5 print c
输出:
01 Hello Sina
02 H
03 H
04 e
05 l
06 l
07 o
08
09 S
10 i
11 n
12 a
b) 字符串格式化
温馨提示:此“格式化”非全清的那种格式化~
字符串格式化使用字符串格式化操作符即百分号%来实现。
如输入:
1 str1='Hello,%s' % 'Sina.'
2 print str1
格式化操作符的右操作数可以是任何东西,如果是元组或者映射类型(如字典),那么字符串格式化将会有所不同。
1 strs=('Hello','Sina') #元组
2 str1='%s,%s' % strs
3 print str1
4 d={'h':'Hello','S':'Sina'} #字典
5 str1='%(h)s,%(S)s' % d
6 print str1
输出:
1 Hello,Sina
2 Hello,Sina
PS:如果需要转换的元组作为转换表达式的一部分存在,那么必须将它用圆括号括起来:
1 str1='%s,%s' % 'Hello','Sina'
2 print str1
输出:
1 Traceback (most recent call last):
2 File "F:\Python\test.py", line 2, in <module>
3 str1='%s,%s' % 'Hello','Sina'
4 TypeError: not enough arguments for format string
如果需要输出%这个特殊字符,毫无疑问,我们会想到转义,但是Python中正确的处理方式如下:
1 str1='%s%%' % 100
2 print str1
输出:
1 100%
对数字进行格式化处理,通常需要控制输出的宽度和精度:
1 from math import pi
2 str1='%.2f' % pi #精度2
3 print str1
4 str1='%10f' % pi #字段宽10
5 print str1
6 str1='%10.2f' % pi #字段宽10,精度2
7 print str1
输出:
1 3.14
2 3.141593
3 3.14
字符串格式化是非常丰富的,想深入学习的童鞋请参考官方文档,或者字符串操作小参考
Python中在string模块还提供另外一种格式化值的方法:模板字符串。它的工作方式类似于很多UNIX Shell里的变量替换,如下所示:
1 from string import Template
2 str1=Template('$x,$y!')
3 str1=str1.substitute(x='Hello',y='Sina')
4 print str1
输出:
1 Hello,Sina!
如果替换字段是单词的一部分,那么参数名称就必须用括号括起来,从而准确指明结尾:
1 from string import Template
2 str1=Template('Hello,S${x}a!')
3 str1=str1.substitute(x='in')
4 print str1
输出:
1 Hello,Sina! (这是有没有跟shell的变量很像!)
如要输出$符,可以使用$$输出:
1 from string import Template
2 str1=Template('$x$$')
3 str1=str1.substitute(x='100')
4 print str1
输出:
1 100$
除了关键字参数之外,模板字符串还可以使用字典变量提供键值对进行格式化:
1 from string import Template
2 d={'h':'Hello','S':'Sina'}
3 str1=Template('$h,$S!')
4 str1=str1.substitute(d)
5 print str1
输出:
1 Hello,Sina!
除了格式化之外,Python字符串还内置了很多实用方法,可参考官方文档,这里不再列举啦
1.4 通用序列操作(方法)
从列表、元组以及字符串可以“抽象”出序列的一些公共通用方法。这些操作包括:索引(indexing)、分片(sliceing)、加(adding)、乘(multiplying)以及检查某个元素是否属于序列的成员。除此之外,还有计算序列长度、最大最小元素等内置函数……
好多好多,这里抛砖引玉,有兴趣的童鞋可以点击通用序列操作参考
二、映射(字典)
映射就像是字典一样,你可以根据一个键值准确地查找到想要的数据。
映射中的每个元素都有一个名字,这个名字的专业名称就叫键。字典(也叫散列表)是Python中唯一内建的映射类型。
映射的键必须唯一。
键可以为任何不可变类型。
字典的键可以是数字、字符串或者是元组。
在Python中,数字、字符串和元组都被设计成不可变类型,而常见的列表以及集合(set)都是可变的,所以列表和集合不能作为字典的键。
1 list1=["hello,world"]
2 set1=set([123])
3 d={}
4 d1=1
5 print d
6 d[list1]="Hello world."
7 d[set1]=123
8 print d
输出:
1 {1: 1}
Traceback (most recent call last):
File "F:\Python\test.py", line 6, in <module>
d[list1]="Hello world."
TypeError: unhashable type: 'list'
自动添加
即使键在字典中并不存在,也可以为它分配一个值,这样字典就会建立新的项。
成员资格
表达式item in d(d为字典)查找的是键(containskey),而不是值(containsvalue)。
Python字典当然还包括内置了很多常用操作方法,可参考官方文档,这里不再列举啦。
三、集合set
集合就是由序列(或者其他可迭代的对象)构建的,如下所示:
1 strs=set(['sina','Weibo','beijing'])
2 nums=set(range(10))
这里主要说的是集合的特征。
3.1 集合特征
a) 忽略副本
忽略副本的意思呢,是说集合会自动忽略其中重复的元素,比如说
若输入:
1 set1=set([0,1,2,3,0,1,2,3,4,5])
2 print set1
3
4 set2=set([0,1,2,3,4,5])
5 print set2
则输出:
1 set([0, 1, 2, 3, 4, 5])
2 set([0, 1, 2, 3, 4, 5])
b) 集合中的元素没有顺序概念
这就是说,Python集合中的元素输出时,不一定按照你的输入顺序,也不一定会按递增或递减的顺序。
set是无序集合,python不保证其中元素的次序。打印结果取决于其内部存储结构和输出方式~就这样。
比如下面这个例子
若输入:
set('012345678910')
则输出:
set(['1', '0', '3', '2', '5', '4', '7', '6', '9', '8'])
可以看出set是先剔除重复元素,然后按某种顺序输出剩下的元素。
3.2 集合的常用方法
a) 交集union
union操作返回两个集合的并集,不改变原有集合。使用按位与(OR)运算符“|”也可以得到一样的结果.
我再举个栗子吧~
比如输入:
1 set1=set([1,2,3])
2 set2=set([2,3,4])
3 set3=set1.union(set2)
4 set4=set1|set2
5 print set1
6 print set2
7 print set3
则会输出:
1 set([1, 2, 3])
2 set([2, 3, 4])
3 set([1, 2, 3, 4])
4 set([1, 2, 3, 4])
PS:其他常见操作还有:&(交集),<=,>=,-,copy()等等一堆啦,有兴趣的孩子请点击这里
b) add和remove
和序列添加和移除的方法非常类似,可参考官方文档:
1 set1=set([1])
2 print set1
3 set1.add(2)
4 print set1
5 set1.remove(2)
6 print set1
7 print set1
8 print 29 in set1
9 set1.remove(29) #移除不存在的项
输出:
1 set([1])
2 set([1, 2])
3 set([1])
4 set([1])
5 False
Traceback (most recent call last):
File "F:\Python\test.py", line 9, in <module>
set1.remove(29) #移除不存在的项
KeyError: 29
3.3 frozenset
集合是可变的,所以不能用做字典的键。集合本身只能包含不可变值,所以也就不能包含其他集合:
1 set1=set([1])
2 set2=set([2])
3 set1.add(set2)
输出如下:
Traceback (most recent call last):
File "F:\Python\test.py", line 3, in <module>
set1.add(set2)
TypeError: unhashable type: 'set'
可以使用frozenset类型用于代表不可变(可散列)的集合:
1 set1=set([1])
2 set2=set([2])
3 set1.add(frozenset(set2))
4 print set1
输出:
1 set([1, frozenset([2])])
python的数据结构总的来说还是比较容易理解和人性化的,这里给出的是一些比较常用的例子。