列表和字典
列表和字典这两个对象类型都是其他对象的集合。这两种类型几乎是Python所有脚本的主要工作组件。这两种类型都相当灵活:它们都可以在原处进行修改,也可以按需求增长或缩短,而且可以包含任何种类的对象或者被嵌套。借助这些类型,可以在脚本中创建并处理任意的复杂的信息结构。
列表
列表是Python中最具灵活性的有序集合对象类型。与字符串不同的是,列表可以包含任何种类的对象:数字、字符串甚至其他列表。同样,与字符串不同,列表是可变对象,支持在原处修改的操作, 可以通过指定的偏移值和分片、列表方法调用、删除语句等方法来实现。
Python中的列表可以完成大多数集合体数据结构的工作,
python列表属性
任意对象的有序集合
从功能上看,列表就是收集其他对象的地方,可以把它们看做组。同时列表所包含的每一项都保持了从左到右的位置顺序(也就是说,它们是序列)。
通过偏移读取
可以通过的偏移对列表对象进行索引,从而读取对象的某一部分内容。由于列表的毎一项都是有序的,那么可以执行如分片和合并之类的任务。
可变长度、异构以及任意嵌套
列表可以实现的增长或者缩短(长度可变),并且可以包含任何类型的对象(异构)。因为列表能够包含其他复杂的对象,又能够支持任意的嵌套,所以可以创建列表的子列表的子列表.....
属于可变序列的分类
就类型分类而言,列表支持在原处的修改(它们是可变的),也可以使用所有针对字符串序列的操作,例如,索引、分片以及合并这样的序列操作在列表与字符串中的工作方式是相同的。唯一的区别是:当应用于字符串上的合并和分片这样的操作应用于列表时,是返回新的列表对象。然而列表是可变的,因此列表也支持字符串不支持的其他操作(例如,删除和索引赋值操作,切片赋值操作,它们都是在原处修改列表)。
对象引用数组
Python列表包含了零个或多个其他对象的引用,从Python的列表中读取一个项的速度与索引一个C语言数组差不多。实际上,在标准Python解释器内部,列表就是C数组而不是链接结构。(每当用到引用时,Python总是会将这个引用指向一个对象,所以程序只需处理对象的操作。当把一个对象赋给一个数据结构元素或变量名时,Python总是会存储对象的引用,而不是对象的一个拷贝(除非明确要求保存拷贝))
列表常量和操作
可以査阅Python的标准库手册,或者运行help(list)或dir(list)査看list方法的完整列表清单,也可以传入一个真正的列表,或者列表数据类型的名称——list这个单单词获取
列表常量与操作
序列操作
1.len(list):列表元素个数
2.max(list):返回列表元素最大值
3.min(list):返回列表元素最小值
4.list(tuple):将元组转换为列表
5.list(str):将字符串转换成列表
列表内置方法
6.l1 = [] :创建一个空列表
7.l3 = [1,'b']:列表异构
8.l4 = [[1,2],['a','b']]:列表嵌套
9.l2[1:3] = [] :把指定的切片定义为空
10.del(list[]):删除列表中的某元素或切片 #del list[]
11.list.append();在列表末尾添加新的对象(只能添加一个元素);也可将另一个序列(列表、元组)当成一个元素附加至当前列表的末尾(用于实现列表嵌套)
12.list.extend();在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表)
13.list.count():用于统计指定值在列表中出现的次数
14.list.index():查找列表中指定值第一次出现的位置
15.list.insert(index,object):在指定索引(偏移)位置之前插入一个对象
16.list.pop():弹出列表中某一个指定索引中的元素;并且返回该元素的值,默认弹出最后一个索引中的元素
17.list. remove():删除指定值第一次出现的位置
18.list.reverse():在原处直接进行逆序
19.list.sort():原处排序(升序)
20.list.clear():清空列表,成为一个空列表
20.列表相加:
l1 + l2 :合并两个列表,返回一个新的列表,不会修改原列表
21.列表相称操作:
list * N: 把list中的元素重复N次,返还一个新列表,
22.列表in操作
in:成员关系判断字符;#在指定的容器中是否出现了指定的元素(存在为True,不存在为False)
用法:
object in container
列表not in操作
not in:成员关系判断字符;#在指定的容器中是否出现了指定的元素(存在为False,不存在为True)
用法:
object not in container
23.列表复制方式
方法1:l1 = [1,2,3];l2 = l1[:] ; 定义l2等于l1中的所有元素
方法2:导入模块copy 使用copy.deepcopy方法;深度复制一个指定的内存对象
import copy
l2 = copy.deepcopy(l1)
基本列表操作
由于列表是序列,它支持与字符串很多相同的操作,例如:“+” 表示合并,“*”表示重复,这两个操作的结果都是创建了一个新的列表
>>> [1, 2, 3] + [4, 5, 6]
[1, 2, 3, 4, 5, 6]
>>> ['Ni!'] * 4
['Ni!', 'Ni!', 'Ni!', 'Ni!']
列表的“+”操作和字符串中的一样,但是“+”两边必须是相同类型的序列对象,否则运行时会出现类型错误。
例如,不能将列表和字符串“+”合并到一 起,除非先把列表转换为字符串(使用诸如反引号、str或者%格式这样的工具),或者是把字符串转换为列表(列表内置函数能完成这一转换)
>>> [1, 2] + "34" #错误提示如下
Traceback (most recent call last):
File "", line 1, in
TypeError: can only concatenate list (not "str") to list
>>> str([1,2]) + "34" #将列表通过内置函数str()转换为字符串,在与字符串“34”合并
'[1, 2]34'
>>> [1,2]+list("34") #将字符串“34”通过内置函数list()转换为字符串,在与列表[1,2]合并
[1, 2, '3', '4']
列表迭代和解析
字符串使用的所有序列操作都一样适用与列表,包括迭代工具
>>> for x in [1,2,3]:
... print(x, end=' ')
...
1 2 3
>>> 3 in [1, 2, 3]
True
for循环从左到右遍历序列中的每一项,对每一项执行一条语句或多条语句,列表解析是通过对序列中的每一项应用一个表达式,来构建一个新的列表的方式,它与for相关
>>> res = [ c * 4 for c in 'SPAM']
>>> res
['SSSS', 'PPPP', 'AAAA', 'MMMM']
这个表达式功能上等同于手动构建一个结果的列表的一个for循环
>>> res = []
>>> for c in 'SPAM':
... res.append(c * 4)
...
>>> res
['SSSS', 'PPPP', 'AAAA', 'MMMM']
内置函数map也做类似的工作,但它是对序列中的每一项应用一个函数并把结果收集到一个新的列表中
>>> list(map(abs, [-1, -2, 0, 1, 2]))
[1, 2, 0, 1, 2]
索引、分片和矩阵
由于字符串和列表都是序列,对于列表而言,索引和分片与字符串的操作基本相同,对列表进行索引的结果就是指定偏移处的对象(无论对象是什么类型)并返回一个新的列表,而对列表进行分片也是返回一个新的列表
>>> L = ['spam', 'Spam', 'SPAM!']
>>> L[2] #索引
'SPAM!'
>>> L[-2] #负索引
'Spam'
>>> L[1:] #切片, 结果是返回一个新的列表
['Spam', 'SPAM!']
由于可以在列表中嵌套列表(和其他对象类型),有时需要将几次索引操作连在一起使用来深入到数据结构中去,最简单的方法之一是将列表表示为矩阵(多维数组),在python中相当于嵌套了子列表的列表,这里是一个基于列表的 3x3 的二维数组
>>> matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
使用一次索引,会得到一个嵌套的子列表,如果使用两次索引才能得到某一子列表中的其中一项
>>> matrix[1]
[4, 5, 6]
>>> matrix[1][1]
5
>>> matrix[2][0]
7
>>> matrix[2][-1]
9
原处修改列表
列表是可变的,支持原处改变列表对象的操作,但是,如果在原处修改一个对象时,可能会影响到一个以上指向它的引用
>>> L = ['spam', 'Spam', 'SPAM!']
>>> L[1] = 'eggs' #将列表L中偏移为1的元素值修改为'eggs'
>>> L
['spam', 'eggs', 'SPAM!']
>>> L[0:2] = ['eat', 'mote'] #分片赋值
>>> L
['eat', 'mote', 'SPAM!']
索引和分片的赋值都是在原处修改,而不是生成一个新的列表对象
列表分片赋值,可以分成两步理解:
1, 删除,删除等号左边指定的分片
2, 插入,将等号右边的对象中插入到左边分片被删除的位置
这样有助于理解为什么插入元素的数目不需要于删除的数目相匹配,例如,已知一个列表L的值为[1,2,3],陚值操作L[1:2] = [4,5]会把L修改成列表 [1,4,5,3]。Python会先删除2 (单项分片),然后在删除2的地方插入4和5。这也解释了为什么L[l:2] = []实际上是刪除操作——Python刪除分片(偏移为1的项)之后什么也不插入。
分片陚值是一次性替换整个片段。因为被賦值的序列长度不一定要与陚值的分片的长度相匹配,所以分片陚值能够用来替换、增长、 缩短主列表。在实践当中这是不常见的操作
列表方法调用
列表方法调用很多是原处修改主体列表的
>>> L
['eat', 'mote', 'SPAM!']
>>> L.append('please')
>>> L
['eat', 'mote', 'SPAM!', 'please']
>>> L.sort()
>>> L
['SPAM!', 'eat', 'mote', 'please']
方法是附属于特定对象的函数(方法实际上是引用函数的属性)方法提供特定类型的工具, 例如列表的方法只能适用于列表
append方法:是简单的将一个单项(对象引用)追加至列表末端,与合并“+”不同的是,append允许传入单一个对象而不是列表(如果传入的是一个列表或元组,也会把列表看着是一个元素来追加至当前列表末端),L.append(x)与L+[x]的结果类似,不同的是,L.append(x)是直接原处修改L, L+[x]会生成新的列表
sort方法:对列表进行原处排序,sort是使用python标准的比较校验作为默认值,以递增的顺序进行排序(升序)
改变sort方法的排序行为:可以通过传入关键字参数来修改排序行为,这里是指按名称的函数调用中特殊的“name=value”语法,常常用来给定配置选项,在排序中,key参数给出了一个单个参数的函数,它返回在排序中使用的值,reverse参数允许排序是按照降序而不是升序进行
>>> L = ['abc', 'ABD', 'aBe']
>>> L.sort()
>>> L
['ABD', 'aBe', 'abc']
>>> L = ['abc', 'ABD', 'aBe']
>>> L.sort(key=str.lower)
>>> L
['abc', 'ABD', 'aBe']
>>> L = ['abc', 'ABD', 'aBe']
>>> L.sort(key=str.lower, reverse=True) #其结果等效于:L.sort() , L.reverse()
>>> L
['aBe', 'ABD', 'abc']
注意啦!
在Python 2.6中不同类型的对象是可进行比较的(例如,字符串和列表)---- python在不间类型之中都定义了一个固定的顺序,也就是说,次序是根据的类型名称而定的。例如,所有整数都小于所有字符串,因为”int"比”str"小。比较运算时绝不会自动转换类型,除非是在比较数值类型对象。
在Python 3.0中,不同类型的比较不再依赖于固定的跨类型之间的排序,而是引发一个异常。因为排序是在内部进行比较,这意味着[1, 2,'spam'].sort()在Python 2.X中是能行得通的,但是在Python 3.0中则会发生异常。Python 3.0也不再支持:传入一个任意的比较函数来进行排序以实现不同的顺序。解决方法是使用key=func关键字参数在排序时编码值的转换,并且使用reverse=True关键字参数把排序顺序改为降序。这些都是过去比较函数的典型用法。
append和“+”合并不同,append不会创建一个新的对象,执行效率很高,也可以使用分片运算模拟append的效果,L[len(L):] = [x]就与L.append(x)一样,而L[:0]=[x]就好像在列表前段附加一样,两者都会删除空分片,并插入X,快速地在适当之处修改L,就像append一样
append和sort都是原处修改列表对象,两者返回的值皆为None(而结果并没有返回列表)。如果编辑类似L=L.append(X)的语句,将不会得到L 修改后的值(实际上,将会失去整个列表的引用),当使用append和sort之类的属性时, 对象的修改有点像副作用,所以没有理由再重新赋值。
内置函数sorted()
排序也在最新的Python版本中可以作为内置函数sorted()使用了,它可以排序任何集合(序列)(不只是列表) 并且针对结果返回一个新的列表(而不是原处修改)
>>> L = ['abc', 'ABC', 'aBc']
>>> sorted(L, key=str.lower, reverse=True)
['abc', 'ABC', 'aBc']
>>> sorted([x.lower() for x in L], reverse=True)#等效于:sorted((x.lower() for x in L), reverse=True)
['abc', 'abc', 'abc']
sorted([x.lower() for x in L], reverse=True) -- 我们可以用一个列表解析在排序之前转换为小写,但是结果不包含最初的列表的值,因为这是用key参数来实现的。后者在排序中临时应用,而不会改变排序的值。内置函数sorted有时候比sort方法更有用。(内置函数sorted():会创建一个新的对象,不会修改原对象)
内置函数reverse()
与字符串相同,列表有其他方法可执行特定的操作。例如,reverse可原地反转列表,extend和pop方法分别能够在末端插入多个元素、刪除一个元素。也有一个 reversed内置函数,像sorted—样地工作,但是,它必须包装在一个list调用中,因为它是一个迭代器
>>> L = [1, 2]
>>> L.extend([3,4,5])
>>> L
[1, 2, 3, 4, 5]
>>> L.pop()
5
>>> L
[1, 2, 3, 4]
>>> L.reverse()
>>> L
[4, 3, 2, 1]
>>> list(reversed(L))
[1, 2, 3, 4]
在某些类型的应用程序中,会把列表的pop和append方法连用,来实现快速的后进先出,(LIFO, last-in-first-out)堆栈结构,列表的末端作为堆栈的顶端:
>>> L = []
>>> L.append(1)
>>> L.append(2)
>>> L
[1, 2]
>>> L.pop()
2
>>> L
[1]
pop方法也能接受某一个即将删除并返回的元素的偏移(默认值为最后一个元素),偏移是可选的,其他的列表方法可以通过值删除(remove)某元素,在偏移处之前插入(insert)某元素,查找某元素的偏移(index)等
>>> L = ['spam','eggs','ham']
>>> L.index('eggs')
1
>>> L.insert(1, 'toast')
>>> L
['spam', 'toast', 'eggs', 'ham']
>>> L.remove('eggs')
>>> L
['spam', 'toast', 'ham']
>>> L.pop(1)
'toast'
>>> L
['spam', 'ham']
其他常用的列表操作
由于列表是可变的支持原处修改,可以使用del语句在原处删除某项或某片段(del语句或者是del()函数)
>>> L = ['SPAM!','eat', 'mote', 'please']
>>> del L[0]
>>> L
['eat', 'mote', 'please']
>>> del L[1:]
>>> L
['eat']
>>> L = ['SPAM!','eat', 'mote', 'please']
>>> del(L[0])
>>> L
['eat', 'mote', 'please']
>>> del(L[1:])
>>> L
['eat']
分片赋值式删除外加插入操作,也可以通过将空列表赋值给分片,来删除列表片段(L[i:j]=[]),python 会删除左侧的分片,然后什么也不插入,另一方面,将空列表赋值给一个索引只会在指定的位置存储空列表的引用,而不是删除
>>> L = ['Already', 'got', 'one']
>>> L[1:] = []
>>> L
['Already']
>>> L[0] = []
>>> L
[[]]