数据结构
Learn from python2.7 official documentation
5.1 List
A list of list object methods:
1 | #在列表末尾添加一个项目 |
5.1.1 List作为stack栈
将列表尾部作为栈顶,使用方法:
1 | list.append(x) |
5.1.2 List作为Queue队列
由于在List的开头(index==0)插入或弹出元素十分低效,若要实现一个Queue,可使用collections.deque。deque结构被设计成可以快速地从两端插入或弹出元素。
1 | #添加引用 |
5.1.3 函数式编程Functional Programming工具
5.1.3.1 filter(function, sequence)
函数filter()
返回sequence
中使function
返回值为true
的元素组成的新List
。
注意:sequence
为str
,unicode
或者tuple
时,filter()
的返回值将会是同样的类型。
1 | #使用filter返回能被3或5整除的数 |
5.1.3.2 map(function, sequence)
函数map()
为sequence
中的每个元素item调用function(item)
,返回由function(item)
结果组成的List
。
1 | #使用map计算三次方 |
一个或多个sequence
可以被作为参数传递,这取决于函数function
参数列表中的参数数量。如果某个sequence
的长度小于其他,相应项取None
。
5.1.3.3 reduce(function, sequence [,starting value])
函数reduce()
从sequence
中选取前两项作为function
的参数,之后每次用前一次function
的返回值和sequence
的下一项作为function
的参数,如此迭代整个sequence
,返回唯一的结果。
1 | #使用reduce计算1-10的和 |
注意:当sequence只有一个元素时,直接返回其值;当sequence为空时,将会引发异常(TypeError: reduce() of empty sequence with no initial value
)。
避免sequence=[]时出现异常的做法,是使用reduce()的第三个参数作为starting value,第一次迭代将使用次参数和sequence的第一个值。
使用第三个参数的例子:
1 | def sum(seq): |
注意:sum(sequence)
已作为python的内置函数提供,功能相同。
5.1.4 列表推导式List Comprehensions
列表推导式提供了更简单的创建列表的方法。
语法:[表达式 for子句 零个或多个for子句或if子句]
1 | #创建一个平方列表 |
应用复杂的表达式和嵌套函数:
1 | from math import pi |
列表推导式的嵌套:
1 | matrix = [ |
注意:zip([iterable, ...])
已作为python的内置函数提供,功能相同。
5.2 del语句
del
语句可用于从给定index的列表中删除项item
,还可用于从列表中删除切片slices
或清除整个列表。
1 | #删除index==0的item |
5.3 元组Tuple和序列Sequence
Tuple
和Sequence
是两种标准序列类型(standard sequence data type)。
之前介绍的List
和Str
是属于Sequence
数据类型中的两种,所以列表和字符串之间有很多共同特性。
这里介绍元组Tuple
,一个元组由几个被逗号隔开的值组成:
1 | t = 12345, 54321, 'hello!' |
元组可以是嵌套的(nested):
1 | u = t, (1, 2, 3, 4, 5) |
元组本身的元素一旦创建将是不可改变的(immutable),给元组中的一个单独的元素赋值将引发异常:
1 | t[0] = 88888 |
但,元组可以包含可改变的(mutable)对象:
1 | v = ([1, 2, 3], [3, 2, 1]) |
构造包含0个或1个元素的元组:
1 | #构造空元组 |
之前使用语句t = 12345, 54321, 'hello!'
构造元组的例子被称为元组打包(tuple packing),对应的,其逆操作被称为元组解包(sequence unpacking),下面是元组解包的例子:
1 | t = 12345, 54321, 'hello!' |
注意:解包时需要左侧的变量列表具有与序列长度相同的元素数量,否则将引发异常(ValueError: too many values to unpack
或ValueError: need more than [num] values to unpack
)。
5.4 集合Set
集合Set
类型是由不重复元素组成的无序的集,基本用法包括成员查找和消除重复元素。
集合对象也支持并集(union),交集(intersection),差集(difference)和对称差分(symmetric difference)等数学运算。
构造集合可以使用set()
函数或花括号,集合在创建时会自动清除重复元素:
1 | #使用set()函数 |
注意:创建空集合只能使用set()
函数
集合提供快速的成员检索:
1 | print 'orange' in fruit |
集合之间的运算:
1 | a = set('abracadabra') |
类似于列表推导式,集合也支持集合推导式set comprehensions
:
1 | a = {x for x in 'abracadabra' if x not in 'abc'} |
5.5 字典Dictionary
数据类型字典Dictionary
以关键字keys
为索引,关键字可以是任意不可变类型(immutable type),通常是字符串string
或数字number
。
如果一个元组只包含字符串、数字或元组,那么这个元组也可以作为关键字。但如果元组直接或间接包含了其他可变对象,那么它就不能用作关键字。
列表不能用作关键字。
构造字典可以使用花括号包含用逗号分隔的键值对(key: value pairs):
1 | tel = {'jack': 4098, 'sape': 4139} |
使用新的关键字并赋值,会为字典添加新的键值对;
使用已存在的关键字进行赋值,会修改字典中已存在的键值对:
1 | tel['guido'] = 4127 |
keys()
方法返回字典中所有关键字组成的列表;
del()
方法删除字典中已存在的键值对:
1 | print tel.keys() |
使用in
来判断某个关键字是否存在于字典中:
1 | print 'guido' in tel |
dict()
构造函数可以直接使用键值对Sequence
来创建字典:
1 | telp = dict([('sape', 4139), ('guido', 4127), ('jack', 4098)]) |
字典同样支持字典推导式(dictionary comprehensions):
1 | print {x: x**2 for x in (2, 4, 6)} |
当关键字是简单字符串(simple strings)时,可以使用关键字参数来指定键值对,有时这将更加方便:
1 | print dict(sape=4139, guido=4127, jack=4098) |
5.6 循环的技巧
当在Sequence
中循环时,可以使用enumerate()
函数将index
和value
同时取出:
1 | for i, v in enumerate(['tic', 'tac', 'toe']): |
当同时在两个或更多Sequence
中循环时,可以用zip()
函数将其内元素一一匹配:
1 | questions = ['name', 'quest', 'favorite color'] |
如果要逆向循环一个Sequence
,可以先正向定位它,然后调用reversed()
函数:
1 | for i in reversed(xrange(1, 10, 2)): |
如果要按某个指定顺序循环一个Sequence
,可以用 sorted()
函数,它可以在不改动原序列的基础上返回一个排好序的新序列:
1 | basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana'] |
当在检索Dictionary
时,可以使用iteritems()
函数同时获取key
和value
:
1 | knights = {'gallahad': 'the pure', 'robin': 'the brave'} |
5.7 深入条件控制
5.7.1 优先级
由高到低:数值运算符 –> 比较操作符 –> 布尔运算符
布尔运算符中优先级由高到低:not –> and –> or
5.7.2 短路运算符(short-circuit operators)
布尔运算符中的and
和or
也被称为短路运算符,它们的参数从左至右解析,一旦可以确定结果,解析停止。
5.7.3 其他
while
和 if
条件句中可以使用任意操作,而不仅仅是比较操作。
比较操作符 in
和 not in
校验一个值是否在(或不在)一个序列里。
操作符 is
和 is not
比较两个对象是不是同一个对象,这只跟像列表这样的可变对象有关。
Python中,赋值操作不能发生在表达式内部。
5.8 比较序列和其他类型
序列对象(Sequence objects)可以与具有相同序列类型的其他对象进行比较。
比较使用lexicographical ordering
:首先比较前两个item
,如果它们不同,则决定比较的结果;如果它们相等,则比较后面的两个item
,以此类推,直到其中一个序列遍历完成。
如果要比较的两个item
本身是同一类型的序列,则递归地进行lexicographical comparison
比较。
注意:比较不同类型的对象是合法的。结果是确定的,但是是任意的,类型按它们的名称排序。因此,一个列表总是小于一个字符串,一个字符串总是小于一个元组,等等。