诺森图书音像专营店
  • 扫码下单

  • 音像Python程序设计基础(第2版计算机系列教材)编者:董付国
  • 正版
    • 作者: 编者:董付国著 | 编者:董付国编 | 编者:董付国译 | 编者:董付国绘
    • 出版社: 清华大学音像出版社
    • 出版时间:2018-01-01
    送至
  • 由""直接销售和发货,并提供售后服务
  • 加入购物车 购买电子书
    服务

    看了又看

    商品预定流程:

    查看大图
    /
    ×

    店铺装修中

    商家:
    诺森图书音像专营店
    联系:
    • 商品

    • 服务

    • 物流

    搜索店内商品

    诺森图书音像专营店

  • 商品参数
    • 作者: 编者:董付国著| 编者:董付国编| 编者:董付国译| 编者:董付国绘
    • 出版社:清华大学音像出版社
    • 出版时间:2018-01-01
    • 版次:2
    • 印次:1
    • 印刷时间:2018-01-01
    • ISBN:9787302490562
    • 版权提供:清华大学音像出版社
    • 作者:编者:董付国
    • 著:编者:董付国
    • 装帧:暂无
    • 印次:1
    • 定价:49.00
    • ISBN:9787302490562
    • 出版社:清华大学
    • 开本:暂无
    • 印刷时间:2018-01-01
    • 语种:暂无
    • 出版时间:2018-01-01
    • 页数:暂无
    • 外部编号:30095068
    • 版次:2
    • 成品尺寸:暂无

    章 管中窥豹:Python概述
    1.1 Python是这样一种语言
    1.2 Python版本之争
    1.3 Python编程规范与代码优化建议
    1.4 Anaconda3开发环境的安装与使用
    1.5 安装扩展库的几种方法
    1.6 标准库与扩展库中对象的导入与使用
    1.6.1 import模块名[as 别名]
    1.6.2 from模块名import对象名[as别名]
    1.6.3 from模块名 import *
    1.7 __name__属的作
    本章小结
    习题
    第2章 万丈高楼平地起:运算符、表达式与内置对象
    2.1 Python常用内置对象
    2.1.1 常量与变量
    2.1.2 数字
    2.1.3 字符串与字节串
    2.1.4 列表、元组、字典、集合
    2.2 Python运算符与表达式
    2.2.1 算术运算符
    2.2.2 关系运算符
    2.. 成员测试运算符in与同一测试运算符is
    2.2.4 位运算符与集合运算符
    2.2.5 逻辑运算符
    2.2.6 矩阵乘法运算符@
    2.2.7 补充说明
    . Python关键字简要说明
    2.4 Python常用内置函数用法精要
    2.4.1 类型转换与类型判断
    2.4.2 值与求和
    2.4.3 基本输入输出
    2.4.4 排序与逆序
    2.4.5 枚举
    2.4.6 map()、reduce()、filter()
    2.4.7 range()
    2.4.8 zip()
    2.4.9 eval()
    2.5 精彩案例赏析
    本章小结
    习题
    第3章 玄之又玄,众妙之门:详解Python序列结构
    3.1 列表:打了激素的数组
    3.1.1 列表创建与删除
    3.1.2 列表元素访问
    3.1.3 列表常用方法
    3.1.4 列表对象支持的运算符
    3.1.5 内置函数对列表的作 3.1.6 列表推导式语法与应用案例
    3.1.7 切片操作的强大功能

    第3章第3章玄之又玄,众妙之门:详解Python序列结构Python中常用的序列结构有列表、元组、字典、字符串、集合等(虽然有人并不主张把字典和集合看作序列,但这真的不重要)。从有序这个角度看,Python序列可以分为有序序列和无序序列;从可变来看,Python序列则可以分为可变序列和不可变序列两大类,如图31所示。另外,生成器对象和range、map、enumerate、filter、zip等对象的某些用法也类似于序列,尽管这些对象更大的特点是惰求值。列表、元组、字符串等有序序列以及range对象均支持双向索引,个元素下标为0,第二个元素下标为1,以此类推;如果使用负数作为索引,则个元素下标为-1,倒数第二个元素下标为-2,以此类推。可以使用负整数作为索引是Python有序序列的一大特色,熟练掌握和运用可以大幅度提高开发效率。
    图31Python序列分类示意图3.1列表:打了激素的数组列表(list)是重要的Python内置对象之一,是包含若干元素的有序连续内存空间。当列表增加或删除元素时,列表对象自动进行内存的扩展或收缩,从而保相邻元素之间没有缝隙。Python列表的这个内存自动管理功能可以大幅度减少程序员的负担,但插入和删除非尾部元素时涉及列表中大量元素的移动,会严重影响效率。另外,在非尾部位置插入和删除元素时会改变该位置后面的元素在列表中的索引,这对于某些操作可能会导致意外的错误结果。所以,除非确实有必要,否则应尽量从列表尾部进行元素的追加与删除操作。〖1〗〖2〗Python程序设计基础(第2版)〖1〗第3章玄之又玄,众妙之门:详解Python序列结构〖2〗在形式上,列表的所有元素放在一对方括号[]中,相邻元素之间使用逗号分隔。在Python中,同一个列表中元素的数据类型可以各不相同,可以同时包含整数、实数、字符串等基本类型的元素,也可以包含列表、元组、字典、集合、函数以及任意对象。如果只有一对方括号而没有任何元素则表示空列表。下面几个都是合法的列表对象:\\\\[10,20,30,40\\\\]\\\\[''crunchyfrog'',''rambladder'',''larkvomit''\\\\]\\\\[''spam'',2.0,5,\\\\[10,20\\\\]\\\\]\\\\[\\\\[''file1'',200,7\\\\],\\\\[''file2'',260,9\\\\]\\\\]\\\\[3,5:6,(1,,)\\\\]Python采用基于值的自动内存管理模式,变量并不直接存储值,而是存储值的引用或内存地址,这也是python中变量可以随时改变类型的重要原因。同理,Python列表中的元素也是值的引用,所以列表中各元素可以是不同类型的数据。
    需要注意的是,列表的功能虽然强大,但是负担也比较重,开销较大,在实际开发中,根据实际的问题选择一种合适的数据类型,要尽量避免过多使用列表。
    3.1.1列表创建与删除使用“=”直接将一个列表赋值给变量即可创建列表对象。>>>a_list=\\\\[''a'',''b'',''mpilgrim'',''z'',''example''\\\\]>>>a_list=\\\\[\\\\]#创建空列表也可以使用list()函数把元组、range对象、字符串、字典、集合或可迭代对象转换为列表。需要注意的是,把字典转换为列表时默认是将字典的“键”转换为列表,而不是把字典的元素转换为列表,如果想把字典的元素转换为列表,需要使用字典对象的items()方法明确说明,当然也可以使用values()来明确说明要把字典的“值”转换为列表。>>>list((3,5,7,9,11))#将元组转换为列表\\\\[3,5,7,9,11\\\\]>>>list(range(1,10,2))#将range对象转换为列表\\\\[1,3,5,7,9\\\\]>>>list(''helloworld'')#将字符串转换为列表\\\\[''h'',''e'',''l'',''l'',''o'','''',''w'',''o'',''r'',''l'',''d''\\\\]>>>list(3,7,5)#将集合转换为列表\\\\[3,5,7\\\\]>>>list(''a'':3,''b'':9,''c'':78)#将字典的“键”转换为列表\\\\[''a'',''c'',''b''\\\\]>>>list(''a'':3,''b'':9,''c'':78.items())#将字典的“键:值”对转换为列表\\\\[(''b'',9),(''c'',78),(''a'',3)\\\\]>>>x=list()#创建空列表当一个列表不再使用时,可以使用del命令将其删除,这一点适用于所有类型的Python对象。>>>x=\\\\[1,,\\\\]>>>delx#删除列表对象>>>x#对象删除后无法再访问,抛出异常NameError:name''x''isnotdefined3.1.2列表元素访问创建列表之后,可以使用整数作为下标来访问其中的元素,其中下标为0的元素表示个元素,下标为1的元素表示第2个元素,下标为2的元素表示第3个元素,以此类推;列表还支持使用负整数作为下标,其中下标为-1的元素表示个元素,下标为-2的元素表示倒数第2个元素,下标为-3的元素表示倒数第3个元素,以此类推,如图32所示(以列表[''P'',''y'',''t'',''h'',''o'',''n'']为例)。>>>x=list(''Python'')#创建列表对象>>>x\\\\[''P'',''y'',''t'',''h'',''o'',''n''\\\\]>>>x\\\\[0\\\\]#下标为0的元素,个元素''P''>>>x\\\\[-1\\\\]#下标为-1的元素,个元素''n''图32双向索引示意图3.1.3列表常用方法列表、元组、字典、集合、字符串等Python序列有很多操作是通用的,而不同类型的序列又有一些特有的方法或者支持某些特有的运算符和内置函数。列表对象常用的方法如表31所示。续表表31列表对象常用的方法方法说明append(x)将x追加至列表尾部extend(L)将列表L中的所有元素追加至列表尾部insert(index,x)在列表index位置处插入x,该位置后面的所有元素后移并且在列表中的索引加1,如果index为正数且大于列表长度则在列表尾部追加x,如果index为负数且小于列表长度的相反数则在列表头部插入元素xremove(x)在列表中删除个值为x的元素,该元素之后所有元素前移并且索引减1,如果列表中不存在x则抛出异常pop(\\\\[index\\\\])删除并返回列表中下标为index的元素,如果不指定index则默认为-1,弹出个元素;如果弹出中间位置的元素则后面的元素索引减1;如果index不是\\\\[-L,L)区间的整数则抛出异常,L表示列表长度clear()清空列表,删除列表中的所有元素,保留列表对象index(x)返回列表中个值为x的元素的索引,若不存在值为x的元素则抛出异常count(x)返回x在列表中的出现次数reverse()对列表所有元素进行原地逆序,首尾交换sort(key=None,reverse=False)对列表中的元素进行原地排序,key用来指定排序规则,reverse为False表示升序,True表示降序copy()返回列表的浅复制1.append()、insert()、extend()这3个方法都可以用于向列表对象中添加元素,其中append()用于向列表尾部追加一个元素,insert()用于向列表任意指定位置插入一个元素,extend()用于将另一个列表中的所有元素追加至当前列表的尾部。这3个方法都属于原地操作,不影响列表对象在内存中的起始地址。对于长列表而言,使用insert()方法在列表首部或中间位置插入元素时效率较低。如果确实需要在首部按序插入多个元素,可以先在尾部追加,然后使用reverse()方法进行翻转,或者考虑使用标准库collections中的双端队列deque对象提供的appendleft()方法。>>>x=\\\\[1,,\\\\]>>>id(x)#查看对象的内存地址
    50159368>>>x.append(4)#在尾部追加元素>>>x.insert(0,0)#在指定位置插入元素>>>x.extend(\\\\[5,6,7\\\\])#在尾部追加多个元素>>>x\\\\[0,1,,,4,5,6,7\\\\]>>>id(x)#列表在内存中的地址不变501593682.pop()、remove()、clear()这3个方法用于删除列表中的元素,其中pop()用于删除并返回指定位置(默认是个)上的元素,如果指定的位置不是合法的索引则抛出异常,对空列表调用pop()方法也会抛出异常;remove()用于删除列表中个值与指定值相等的元素,如果列表中不存在该元素则抛出异常;clear()用于清空列表中的所有元素。这3个方法也属于原地操作,不影响列表对象的内存地址。另外,还可以使用del命令删除列表中指定位置的元素,这个方法同样也属于原地操作。>>>x=\\\\[1,,,4,5,6,7\\\\]>>>x.pop()#弹出并返回尾部元素7>>>x.pop(0)#弹出并返回指定位置的元素1>>>x.clear()#删除所有元素>>>x\\\\[\\\\]>>>x=\\\\[1,2,1,1,2\\\\]>>>x.remove(2)#删除值为2的元素>>>delx\\\\[3\\\\]#删除指定位置上的元素>>>x\\\\[1,1,1\\\\]必须强调的是,由于列表具有内存自动收缩和扩张功能,在列表中间位置插入或删除元素时,不仅效率较低,而且该位置后面所有元素在列表中的索引也会发生变化,必须牢牢记住这一点。
    3.count()、index()列表方法count()用于返回列表中指定元素出现的次数;index()用于返回指定元素在列表中首次出现的位置,如果该元素不在列表中则抛出异常。>>>x=\\\\[1,2,,,,3,4,4,4,4\\\\]>>>x.count(3)#元素3在列表x中的出现次数3>>>x.count(5)#不存在,返回00>>>x.index(2)#元素2在列表x中首次出现的索引1>>>x.index(5)#列表x中没有5,抛出异常ValueError:5isnotinlist通过前面的介绍我们已经知道,列表对象的很多方法在特殊情况下会抛出异常,而一旦出现异常,整个程序就会崩溃,这是我们不希望的。为避免引发异常而导致程序崩溃,一般来说有两种方法:①使用选择结构确保列表中存在定元素再调用有关的方法;②使用异常处理结构。下面的代码使用异常处理结构保用户输入的是三位数,然后使用关键字in来测试用户输入的数字在列表中,如果存在则输出其索引,否则提示不存在。fromrandomirtamplelst=sample(range(100,1000),100)whileTrue:x=input(''请输入一个三位数:'')try:assertlen(x)==3,''长度必须为3''x=int(x)breakexcept:passifxinlst:print(''元素0在列表中的索引为:1''.format(x,lst.index(x)))else:print(''列表中不存在该元素.'')4.sort()、reverse()列表对象的sort()方法用于按照指定的规则对所有元素进行排序,默认规则是所有元素从小到大升序排序;reverse()方法用于将列表所有元素逆序或翻转,也就是个元素和倒数个元素交换位置,第二个元素和倒数第二个元素交换位置,以此类推。>>>x=list(range(11))#包含11个整数的列表>>>importrandom>>>random.shuffle(x)#把列表x中的元素随机乱序>>>x\\\\[6,0,1,7,4,3,2,8,5,10,9\\\\]>>>x.sort(key=lambdaitem:len(str(item)),reverse=True)#按转换成字符串以后的长度降序排列>>>x\\\\[10,6,0,1,7,4,3,2,8,5,9\\\\]>>>x.sort(key=str)#按转换为字符串后的大小升序排序>>>x\\\\[0,1,10,,,4,5,6,7,8,9\\\\]>>>x.sort()#按默认规则排序>>>x\\\\[0,1,,,4,5,6,7,8,9,10\\\\]>>>x.reverse()#把所有元素翻转或逆序>>>x\\\\[10,9,8,7,6,5,4,3,2,1,0\\\\]列表对象的sort()和reverse()分别对列表进行原地排序(inplacesorting)和逆序,没有返回值。所谓“原地”,意思是用处理后的数据替换原来的数据,列表首地址不变,列表中元素原来的顺序全部丢失。
    如果不想丢失原来的顺序,可以使用2.4.4节介绍的内置函数sorted()和reversed()。其中,内置函数sorted()返回排序后的新列表,参数key和reverse的含义与列表方法sort()完全相同;内置函数reversed()返回一个逆序后的reversed对象。充分利用列表对象的sort()方法和内置函数sorted()的key参数,可以实现更加复杂的排序,以内置函数sorted()为例:>>>gameresult=\\\\[\\\\[''Bob'',95.0,''A''\\\\],\\\\[''Alan'',86.0,''C''\\\\],\\\\[''Mandy'',83.5,''A''\\\\],\\\\[''Rob'',89.3,''E''\\\\]\\\\]>>>fromoperatorimportitemgetter>>>sorted(gameresult,key=itemgetter(2))#按子列表第3个元素进行升序排序\\\\[\\\\[''Bob'',95.0,''A''\\\\],\\\\[''Mandy'',83.5,''A''\\\\],\\\\[''Alan'',86.0,''C''\\\\],\\\\[''Rob'',89.3,''E''\\\\]\\\\]>>>sorted(gameresult,key=itemgetter(2,0))#先按第3个元素升序并排列,再按个元素升序排序\\\\[\\\\[''Bob'',95.0,''A''\\\\],\\\\[''Mandy'',83.5,''A''\\\\],\\\\[''Alan'',86.0,''C''\\\\],\\\\[''Rob'',89.3,''E''\\\\]\\\\]>>>sorted(gameresult,key=itemgetter(2,0),reverse=True)\\\\[\\\\[''Rob'',89.3,''E''\\\\],\\\\[''Alan'',86.0,''C''\\\\],\\\\[''Mandy'',83.5,''A''\\\\],\\\\[''Bob'',95.0,''A''\\\\]\\\\]>>>list1=\\\\[\\\"what\\\",\\\"I''m\\\",\\\"sorting\\\",\\\"by\\\"\\\\]#以一个列表内容为依据>>>list2=\\\\[\\\"something\\\",\\\"else\\\",\\\"to\\\",\\\"sort\\\"\\\\]#对另一个列表内容进行排序>>>pairs=zip(list1,list2)#把两个列表中的对应位置元素配对>>>\\\\[item\\\\[1\\\\]foriteminsorted(pairs,key=lambdax:x\\\\[0\\\\],reverse=True)\\\\]\\\\[''something'',''to'',''sort'',''else''\\\\]>>>x=\\\\[\\\\[1,,\\\\],\\\\[2,1,4\\\\],\\\\[2,2,1\\\\]\\\\]>>>sorted(x,key=lambdaitem:(item\\\\[1\\\\],-item\\\\[2\\\\]))#以第2个元素升序#第3个元素降序排序#这里的负号只适用于数值型元素\\\\[\\\\[2,1,4\\\\],\\\\[1,,\\\\],\\\\[2,2,1\\\\]\\\\]>>>x=\\\\[''aaaa'',''bc'',''d'',''b'',''ba''\\\\]>>>sorted(x,key=lambdaitem:(len(item),item))#先按长度排序,长度一样的正常排序\\\\[''b'',''d'',''ba'',''bc'',''aaaa''\\\\]5.copy()列表对象的copy()方法返回列表的浅复制。所谓浅复制,是指生成一个新的列表,并且把原列表中所有元素的引用都复制到新列表中。如果原列表中只包含整数、实数、复数等基本类型或元组、字符串这样的不可变类型的数据,一般是没有问题的。但是,如果原列表中包含列表之类的可变数据类型,由于浅复制时只是把子列表的引用复制到新列表中,于是修改任何一个都会影响另外一个。>>>x=\\\\[1,2,\\\\[3,4\\\\]\\\\]#原列表中包含子列表>>>y=x.copy()#浅复制>>>y#两个列表中的内容看起来完全一样\\\\[1,2,\\\\[3,4\\\\]\\\\]>>>y\\\\[2\\\\].append(5)#为新列表中的子列表追加元素>>>x\\\\[0\\\\]=6#整数、实数等不可变类型不受此影响>>>y.append(6)#在新列表尾部追加元素>>>y\\\\[1,2,\\\\[3,4,5\\\\],6\\\\]>>>x#原列表不受影响\\\\[6,2,\\\\[3,4,5\\\\]\\\\]列表对象的copy()方法和切片操作以及标准库copy中的copy()函数一样都是返回浅复制,如果想避免上面代码演示的问题,可以使用标准库copy中的deepcopy()函数实现深复制。所谓深复制,是指对原列表中的元素进行递归,把所有的值都复制到新列表中,对嵌套的子列表不再是复制引用。这样一来,新列表和原列表是互相独立,修改任何一个都不会影响另外一个。>>>importcopy>>>x=\\\\[1,2,\\\\[3,4\\\\]\\\\]>>>y=copy.deepcopy(x)#深复制>>>x\\\\[2\\\\].append(5)#为原列表中的子列表追加元素>>>y.append(6)#在新列表尾部追加元素>>>y\\\\[1,2,\\\\[3,4\\\\],6\\\\]>>>x\\\\[1,2,\\\\[3,4,5\\\\]\\\\]不论是浅复制还是深复制,与列表对象的直接赋值都是不一样的情况。下面的代码把同一个列表赋值给两个不同的变量,这两个变量是互相独立的,修改任何一个都不会影响另外一个。>>>x=\\\\[1,2,\\\\[3,4\\\\]\\\\]>>>y=\\\\[1,2,\\\\[3,4\\\\]\\\\]#把同一个列表对象赋值给两个变量>>>x.append(5)>>>x\\\\[2\\\\].append(6)#修改其中一个列表的子列表>>>x\\\\[1,2,\\\\[3,4,6\\\\],5\\\\]>>>y#不影响另外一个列表\\\\[1,2,\\\\[3,4\\\\]\\\\]下面的代码演示的是另外一种情况,把一个列表变量赋值给另外一个变量,这样两个变量指向同一个列表对象,对其中一个做的任何修改都会立刻在另外一个变量得到体现。>>>x=\\\\[1,2,\\\\[3,4\\\\]\\\\]>>>y=x#两个变量指向同一个列表>>>x\\\\[2\\\\].append(5)>>>x.append(6)>>>x\\\\[0\\\\]=7>>>x\\\\[7,2,\\\\[3,4,5\\\\],6\\\\]>>>y#对x做的任何修改,y都会受到影响\\\\[7,2,\\\\[3,4,5\\\\],6\\\\]3.1.4列表对象支持的运算符加法运算符(+)也可以实现列表增加元素的目的,但这个运算符不属于原地操作,而是返回新列表,并且涉及大量元素的复制,效率低。使用复合赋值运算符+=实现列表追加元素时属于原地操作,与append()方法一样高效。>>>x=\\\\[1,,\\\\]>>>id(x)53868168>>>x=x+\\\\[4\\\\]#连接两个列表>>>x\\\\[1,,,4\\\\]>>>id(x)#内存地址发生改变53875720>>>x+=\\\\[5\\\\]#为列表追加元素>>>x\\\\[1,,,4,5\\\\]>>>id(x)#内存地址不变53875720乘法运算符可以用于列表和整数相乘,表示序列重复,返回新列表,从一定程度上来说也可以实现为列表增加元素的功能。与加法运算符(+)一样,该运算符也适用于元组和字符串。另外,运算符=也可以用于列表元素重复,与运算符+=一样属于原地操作。>>>x=\\\\[1,,,4\\\\]>>>id(x)54497224>>>x=x2#元素重复,返回新列表>>>x\\\\[1,,,4,1,,,4\\\\]>>>id(x)#地址发生改变54603912>>>x=2#元素重复,原地进行>>>x\\\\[1,,,4,1,,,4,1,,,4,1,,,4\\\\]>>>id(x)#地址不变54603912>>>\\\\[1,,\\\\]0#重复0次,清空\\\\[\\\\]成员测试运算符in可用于测试列表中包含某个元素,查询时间随着列表长度的增加而线增加,而同样的操作对于集合而言则是常数级的。>>>3in\\\\[1,,\\\\]True>>>3in\\\\[1,2,''3''\\\\]False3.1.5内置函数对列表的操作除了列表对象自身方法之外,很多Python内置函数也可以对列表进行操作。例如,max()、min()函数用于返回列表中所有元素的值和值,sum()函数用于返回列表中所有元素之和,len()函数用于返回列表中元素的个数,zip()函数用于将多个列表中元素重新组合为元组并返回包含这些元组的zip对象,enumerate()函数返回包含若干下标和值的迭代对象,map()函数把函数映到列表上的每个元素,filter()函数根据指定函数的返回值对列表元素进行过滤,all()函数用来测试列表中所有元素都等价于True,any()函数用来测试列表中有等价于True的元素。>>>x=list(range(11))#生成列表>>>importrandom>>>random.shuffle(x)#打乱列表中元素的顺序>>>x\\\\[0,6,10,9,8,7,4,5,2,1,3\\\\]>>>all(x)#测试所有元素都等价于TrueFalse>>>any(x)#测试存在等价于True的元素True>>>max(x)#返回值
    10>>>max(x,key=str)#按指定规则返回值
    9>>>min(x)0>>>sum(x)#所有元素之和55>>>len(x)#列表元素个数11>>>list(zip(x,\\\\[1\\\\]11))#多列表元素重新组合\\\\[(0,1),(6,1),(10,1),(9,1),(8,1),(7,1),(4,1),(5,1),(2,1),(1,1),(3,1)\\\\]>>>list(zip(range(1,4)))#zip()函数也可以用于一个序列或迭代对象\\\\[(1,),(2,),(3,)\\\\]>>>list(zip(\\\\[''a'',''b'',''c''\\\\],\\\\[1,2\\\\]))#如果两个列表不等长,则以短的为准\\\\[(''a'',1),(''b'',2)\\\\]>>>enumerate(x)#枚举列表元素,返回enumerate对象>>>list(enumerate(x))#enumerate对象可以转换为列表、元组、集合\\\\[(0,0),(1,6),(2,10),(3,9),(4,8),(5,7),(6,4),(7,5),(8,2),(9,1),(10,3)\\\\]3.1.6列表推导式语法与应用案例列表推导式(listcomprehension)也称为列表解析式,可以使用简洁的方式对列表或可迭代对象的元素进行遍历、过滤或再次计算,快速生成满足特定需求的新列表,代码简洁,具有很强的可读,是Python程序开发时应用多的技术之一。Python的内部实现对列表推导式做了大量优化,可以保很快的运行速度,也是使用的一种技术。列表推导式的语法形式为\\\\[expressionforexpr1insequence1ifcondition1forexpr2insequence2ifcondition2forexpr3insequence3ifcondition3forexprNinsequenceNifconditionN\\\\]列表推导式在逻辑上等价于一个循环语句,只是形式上更加简洁。例如:>>>aList=\\\\[xxforxinrange(10)\\\\]相当于>>>aList=\\\\[\\\\]>>>forxinrange(10):aList.append(xx)再如:>>>freshfruit=\\\\[''banana'',''loganberry'',''passionfruit''\\\\]>>>aList=\\\\[w.strip()forwinfreshfruit\\\\]等价于下面的代码:>>>aList=\\\\[\\\\]>>>foriteminfreshfruit:aList.append(item.strip())当然也等价于:>>>aList=list(map(lambdax:x.strip(),freshfruit))或>>>aList=list(map(str.strip,freshfruit))大家应该听过一个故事,说的是阿凡提(也有的说是阿基米德)与国王比赛下棋,国王说要是自己输了阿凡提想要什么他都可以拿得出来。阿凡提说那就要点米吧,棋盘一共64个小格子,在个格子里放1粒米,第二个格子里放2粒米,第三个格子里放4粒米,第四个格子里放8粒米。以此类推,后面每个格子里的米都是前一个格子里的2倍,一直把64个格子都放满。那么到底需要多少粒米呢?使用列表推导式再结合内置函数sum()就很容易知道。>>>sum(\\\\[2iforiinrange(64)\\\\])18446744073709551615按一斤大米约26000粒计算,为放满棋盘,需要大概3500亿吨大米。结果可想而知,国王没有办法拿出那么多米。
    接下来再通过几个示例来进一步展示列表推导式的强大功能。
    1.实现嵌套列表的平铺>>>vec=\\\\[\\\\[1,,\\\\],\\\\[4,5,6\\\\],\\\\[7,8,9\\\\]\\\\]>>>\\\\[numforeleminvecfornuminelem\\\\]\\\\[1,,,4,5,6,7,8,9\\\\]在这个列表推导式中有两个循环,其中个循环可以看作外循环,执行得慢;第二个循环可以看作内循环,执行得快。上面代码的执行过程等价于下面的写法:>>>vec=\\\\[\\\\[1,,\\\\],\\\\[4,5,6\\\\],\\\\[7,8,9\\\\]\\\\]>>>result=\\\\[\\\\]>>>foreleminvec:fornuminelem:result.append(num)>>>result\\\\[1,,,4,5,6,7,8,9\\\\]>>>list(chain(vec))\\\\[1,,,4,5,6,7,8,9\\\\]当然,这里演示的只是一层嵌套列表的平铺,如果有多级嵌套或者不同子列表嵌套深度不同,就不能使用上面的方法了。这时,可以使用函数递归实现。defflatList(lst):result=\\\\[\\\\]#存放结果的列表defnested(lst):#函数嵌套定义foriteminlst:ifisinstance(item,list):nested(item)#递归子列表else:result.append(item)#扁平化列表nested(lst)#调用嵌套定义的函数returnresult#返回结果2.过滤不符合条件的元素在列表推导式中可以使用if子句对列表中的元素进行筛选,只在结果列表中保留符合条件的元素。下面的代码可以列出当前文件夹下所有Python源文件:>>>importos>>>\\\\[filenameforfilenameinos.listdir(''.'')iffilename.endswith((''.py'',''.pyw''))\\\\]下面的代码用于从列表中选择符合条件的元素组成新的列表:>>>aList=\\\\[-1,-4,6,7.5,-.,,-11\\\\]>>>\\\\[iforiinaListifi>0\\\\]#所有大于0的数字\\\\[6,7.5,9\\\\]再如,已知有一个包含一些同学的字典,现在需要计算所有的分、分、平均分,并查找所有分同学,代码可以这样编写:>>>scores=\\\"ZhangSan\\\":45\\\"LiSi\\\":78,\\\"WangWu\\\":40,\\\"ZhouLiu\\\":96,\\\"Zhaoi\\\":65,\\\"SunBa\\\":90,\\\"ZhengJiu\\\":78,\\\"WuShi\\\":99,\\\"DongShiyi\\\":60>>>highest=max(scores.values())#分>>>lowest=min(scores.values())#分>>>average=sum(scores.values())/len(scores)#平均分>>>highest,lowest,average(99,40,7.333333333333)>>>highestPerson=\\\\[nameforname,scoreinscores.items()ifscore==highest\\\\]>>>highestPerson\\\\[''WuShi''\\\\]与上面的代码功能类似,下面的代码使用列表推导式查找列表中元素的所有位置:>>>fromrandomimportrandint>>>x=\\\\[randint(1,10)foriinrange(20)\\\\]#20个介于\\\\[1,10\\\\]的整数>>>x\\\\[10,,,4,5,10,10,9,2,4,10,8,2,2,9,7,6,2,5,6\\\\]>>>m=max(x)>>>\\\\[indexforindex,valueinenumerate(x)ifvalue==m\\\\]#整数的所有出现位置\\\\[0,5,6,10\\\\]3.同时遍历多个列表或可迭代对象>>>\\\\[(x,y)forxin\\\\[1,,\\\\]foryin\\\\[3,1,4\\\\]ifx!=y\\\\]\\\\[(1,3),(1,4),(,),(2,1),(2,4),(3,1),(3,4)\\\\]>>>\\\\[(x,y)forxin\\\\[1,,\\\\]ifx==1foryin\\\\[3,1,4\\\\]ify!=x\\\\]\\\\[(1,3),(1,4)\\\\]对于包含多个循环的列表推导式,一定要清楚多个循环的执行顺序或“嵌套关系”。例如,上面个列表推导式等价于>>>result=\\\\[\\\\]>>>forxin\\\\[1,,\\\\]:foryin\\\\[3,1,4\\\\]:ifx!=y:result.append((x,y))>>>result\\\\[(1,3),(1,4),(,),(2,1),(2,4),(3,1),(3,4)\\\\]4.使用列表推导式实现矩阵转置>>>matrix=\\\\[\\\\[1,,,4\\\\],\\\\[5,6,7,8\\\\],\\\\[9,10,11,12\\\\]\\\\]>>>\\\\[\\\\[row\\\\[i\\\\]forrowinmatrix\\\\]foriinrange(4)\\\\]\\\\[\\\\[1,5,9\\\\],\\\\[2,6,10\\\\],\\\\[3,7,11\\\\],\\\\[4,8,12\\\\]\\\\]对于嵌套了列表推导式的列表推导式,一定要清楚其执行顺序。例如,上面列表推导式的执行过程等价于下面的代码>>>matrix=\\\\[\\\\[1,,,4\\\\],\\\\[5,6,7,8\\\\],\\\\[9,10,11,12\\\\]\\\\]>>>result=\\\\[\\\\]>>>foriinrange(len(matrix\\\\[0\\\\])):result.append(\\\\[row\\\\[i\\\\]forrowinmatrix\\\\])>>>result\\\\[\\\\[1,5,9\\\\],\\\\[2,6,10\\\\],\\\\[3,7,11\\\\],\\\\[4,8,12\\\\]\\\\]如果把内层的列表推导式也展开,完整的执行过程可以通过下面的代码来模拟:>>>matrix=\\\\[\\\\[1,,,4\\\\],\\\\[5,6,7,8\\\\],\\\\[9,10,11,12\\\\]\\\\]>>>result=\\\\[\\\\]>>>foriinrange(len(matrix\\\\[0\\\\])):temp=\\\\[\\\\]forrowinmatrix:temp.append(row\\\\[i\\\\])result.append(temp)>>>result\\\\[\\\\[1,5,9\\\\],\\\\[2,6,10\\\\],\\\\[3,7,11\\\\],\\\\[4,8,12\\\\]\\\\]当然,也可以使用内置函数zip()和list()来实现矩阵转置:>>>list(map(list,zip(matrix)))\\\\[\\\\[1,5,9\\\\],\\\\[2,6,10\\\\],\\\\[3,7,11\\\\],\\\\[4,8,12\\\\]\\\\]5.列表推导式中可以使用函数或复杂表达式>>>deff(v):ifv%2==0:v=v2else:v=v+1returnv>>>print(\\\\[f(v)forvin\\\\[,,4,-1\\\\]ifv>0\\\\])\\\\[4,4,16\\\\]>>>print(\\\\[v2ifv%2==0elsev+1forvin\\\\[,,4,-1\\\\]ifv>0\\\\])\\\\[4,4,16\\\\]6.列表推导式支持文件对象迭代>>>withopen(''C:\\\\\\\\\\\\\\\\RHDSetup.log'',''r'')asfp:#为节约篇幅,略去输出结果print(\\\\[lineforlineinfp\\\\])7.使用列表推导式生成100以内的所有素数>>>\\\\[pforpinrange(2,100)if0notin\\\[pdfordinrange(2,int(sqrt(p))+1)\\\\]\\\\]\\\\[,,5,7,11,13,17,19,,,1,7,41,43,47,53,59,61,67,71,73,79,83,89,97\\\\]3.1.7切片操作的强大功能切片是Python序列的重要操作之一,除了适用于列表之外,还适用于元组、字符串、range对象,但列表的切片操作具有功能。不仅可以使用切片来截取列表中的任何部分返回得到一个新列表,也可以通过切片来修改和删除列表中部分元素,甚至可以通过切片操作为列表对象增加元素。
    在形式上,切片使用2个冒号分隔的3个数字来完成。\\\\[start:end:step\\\\]其中,3个数字的含义与内置函数range(start,end,step)完全一致,个数字start表示切片开始的位置,默认为0;第二个数字end表示切片截止(但不包含)的位置(默认为列表长度);第三个数字step表示切片的步长(默认为1)。当start为0时可以省略,当end为列表长度时可以省略,当step为1时可以省略,省略步长时还可以同时省略个冒号。另外,当step为负整数时,表示反向切片,这时start应该在end的右侧才行。
    1.使用切片获取列表的部分元素使用切片可以返回列表中部分元素组成的新列表。与使用索引作为下标访问列表元素的方法不同,切片操作不会因为下标越界而抛出异常,而是简单地在列表尾部截断或者返回一个空列表,代码具有更强的健壮。>>>aList=\\\\[3,4,5,6,7,9,11,13,15,17\\\\]>>>aList\\\\[::\\\\]#返回包含原列表中所有元素的新列表\\\\[3,4,5,6,7,9,11,13,15,17\\\\]>>>aList\\\\[::-1\\\\]#返回包含原列表中所有元素的逆序列表\\\\[17,15,13,11,9,7,6,5,4,3\\\\]>>>aList\\\\[::2\\\\]#隔一个取一个,获取偶数位置的元素\\\\[3,5,7,11,15\\\\]>>>aList\\\\[1::2\\\\]#隔一个取一个,获取奇数位置的元素\\\\[4,6,9,13,17\\\\]>>>aList\\\\[3:6\\\\]#指定切片的开始和结束位置\\\\[6,7,9\\\\]>>>aList\\\\[0:100\\\\]#切片结束位置大于列表长度时,从列表尾部截断\\\\[3,4,5,6,7,9,11,13,15,17\\\\]>>>aList\\\\[100\\\\]#抛出异常,不允许越界访问IndexError:listindexoutofrange>>>aList\\\\[100:\\\\]#切片开始位置大于列表长度时,返回空列表\\\\[\\\\]>>>aList\\\\[-15:3\\\\]#进行必要的截断处理\\\\[3,4,5\\\\]>>>len(aList)10>>>aList\\\\[3:-10:-1\\\\]#位置3在位置-10的右侧,-1表示反向切片\\\\[6,5,4\\\\]>>>aList\\\\[3:-5\\\\]#位置3在位置-5的左侧,正向切片\\\\[6,7\\\\]2.使用切片为列表增加元素可以使用切片操作在列表任意位置插入新元素,不影响列表对象的内存地址,属于原地操作。>>>aList=\\\\[3,5,7\\\\]>>>aList\\\\[len(aList):\\\\]\\\\[\\\\]>>>aList\\\\[len(aList):\\\\]=\\\\[9\\\\]#在列表尾部增加元素>>>aList\\\\[:0\\\\]=\\\\[1,2\\\\]#在列表头部插入多个元素>>>aList\\\\[3:3\\\\]=\\\\[4\\\\]#在列表中间位置插入元素>>>aList\\\\[1,,,4,5,7,9\\\\]3.使用切片替换和修改列表中的元素>>>aList=\\\\[3,5,7,9\\\\]>>>aList\\\\[:3\\\\]=\\\\[1,,\\\\]#替换列表元素,等号两边的列表长度相等>>>aList\\\\[1,,,\\\\]>>>aList\\\\[3:\\\\]=\\\\[4,5,6\\\\]#切片连续,等号两边的列表长度可以不相等>>>aList\\\\[1,,,4,5,6\\\\]>>>aList\\\\[::2\\\\]=\\\\[0\\\\]3#隔一个修改一个>>>aList\\\\[0,2,0,4,0,6\\\\]>>>aList\\\\[::2\\\\]=\\\\[''a'',''b'',''c''\\\\]#隔一个修改一个>>>aList\\\\[''a'',2,''b'',4,''c'',6\\\\]>>>aList\\\\[1::2\\\\]=range(3)#序列解包的用法>>>aList\\\\[''a'',0,''b'',1,''c'',2\\\\]>>>aList\\\\[1::2\\\\]=map(lambdax:x!=5,range(3))>>>aList\\\\[''a'',True,''b'',True,''c'',True\\\\]>>>aList\\\\[1::2\\\\]=zip(''abc'',range(3))#map、filter、zip对象都支持这样的用法>>>aList\\\\[''a'',(''a'',0),''b'',(''b'',1),''c'',(''c'',2)\\\\]>>>aList\\\\[::2\\\\]=\\\\[1\\\\]#切片不连续时等号两边列表的长度必须相等ValueError:attettasignsequenceofsize1toextendedsliceofsize34.使用切片删除列表中的元素>>>aList=\\\\[3,5,7,9\\\\]>>>aList\\\\[:3\\\\]=\\\\[\\\\]#删除列表中前3个元素>>>aList\\\\[9\\\\]另外,也可以使用del命令与切片结合来删除列表中的部分元素,并且切片元素可以不连续。>>>aList=\\\\[3,5,7,9,11\\\\]>>>delaList\\\\[:3\\\\]#切片元素连续>>>aList\\\\[9,11\\\\]>>>aList=\\\\[3,5,7,9,11\\\\]>>>delaList\\\\[::2\\\\]#切片元素不连续,隔一个删一个>>>aList\\\\[5,9\\\\]5.切片得到的是列表的浅复制在3.1.3节介绍列表对象的copy()方法时曾经提到,切片返回的是列表元素的浅复制,与列表对象的直接赋值并不一样,和3.1.3节介绍的深复制也有本质的不同。>>>aList=\\\\[3,5,7\\\\]>>>bList=aList\\\\[::\\\\]#切片,浅复制>>>aList==bList#两个列表的值相等True>>>aListisbList#浅复制,不是同一个对象False>>>id(aList)==id(bList)#两个列表对象的地址不相等False>>>id(x\\\\[0\\\\])==id(y\\\\[0\\\\])#相同的值在内存中只有一份True>>>bList\\\\[1\\\\]=8#修改bList列表元素的值不会影响aList>>>bList#bList的值发生改变\\\\[3,8,7\\\\]>>>aList#aList的值没有发生改变\\\\[3,5,7\\\\]>>>x=\\\\[\\\\[1\\\\],\\\\[2\\\\],\\\\[3\\\\]\\\\]#如果列表中包含列表或可变序列>>>y=x\\\\[:\\\\]#情况会复杂一些>>>y\\\\[\\\\[1\\\\],\\\\[2\\\\],\\\\[3\\\\]\\\\]>>>y\\\\[0\\\\]=\\\\[4\\\\]#直接修改y中下标为0的元素值,不影响x>>>y\\\\[\\\\[4\\\\],\\\\[2\\\\],\\\\[3\\\\]\\\\]>>>y\\\\[1\\\\].append(5)#通过列表对象的方法原地增加元素>>>y\\\\[\\\\[4\\\\],\\\\[2,5\\\\],\\\\[3\\\\]\\\\]>>>x#列表x也受到同样的影响\\\\[\\\\[1\\\\],\\\\[2,5\\\\],\\\\[3\\\\]\\\\]3.2元组:轻量级列表〖*8/9〗3.2.1元组创建与元素访问列表的功能虽然很强大,但负担也很重,在很大程度上影响了运行效率。有时并不需要那么多功能,很希望能有个轻量级的列表,元组(tuple)正是这样一种类型。在形式上,元组的所有元素放在一对圆括号中,元素之间使用逗号分隔,如果元组中只有一个元素则必须在增加个逗号。>>>x=(1,,)#直接把元组赋值给一个变量>>>type(x)#使用type()函数查看变量的类型>>>x\\\\[0\\\\]#元组支持使用下标访问特定位置的元素1>>>x\\\\[-1\\\\]#个元素,元组支持双向索引3>>>x\\\\[1\\\\]=4#元组是不可变的TypeError:''tuple''objectdoesnotsupportitemassignment>>>x=(3)#这和x=3是一样的>>>x3>>>x=(3,)#如果元组中只有一个元素,必须在后面多写一个逗号>>>x(3,)>>>x=()#空元组>>>x=tuple()#空元组>>>tuple(range(5))#将迭代对象转换为元组(0,1,,,4)除了上面的方法可以直接创建元组之外,很多内置函数的返回值也是包含了若干元组的可迭代对象,如enumerate()、zip()等。>>>list(enumerate(range(5)))\\\\[(0,0),(1,1),(2,2),(3,3),(4,4)\\\\]>>>list(zip(range(3),''abcdefg''))\\\\[(0,''a''),(1,''b''),(2,''c'')\\\\]3.2.2元组与列表的异同点列表和元组都属于有序序列,都支持使用双向索引访问其中的元素,以及使用count()方法统计元素的出现次数和index()方法获取元素的索引,len()、map()、filter()等大量内置函数和+、、+=、in等运算符也都可以作用于列表和元组。虽然列表和元组有着一定的相似之处,但在本质上和内部实现上都有着很大的不同。
    元组属于不可变(immutable)序列,不可以直接修改元组中元素的值,也无法为元组增加或删除元素。所以,元组没有提供append()、extend()和insert()等方法,无法向元组中添加元素;同样,元组也没有remove()和pop()方法,也不支持对元组元素进行del操作,不能从元组中删除元素,而只能使用del命令删除整个元组。元组也支持切片操作,但是只能通过切片来访问元组中的元素,而不允许使用切片来修改元组中元素的值,也不支持使用切片操作来为元组增加或删除元素。从一定程度上讲,可以认为元组是轻量级的列表,或者“常量列表”。
    Python的内部实现对元组做了大量优化,访问速度比列表更快。如果定义了一系列常量值,主要用途仅是对它们进行遍历或类似用途,而不需要对其元素进行任何修改,那么一般建议使用元组而不用列表。元组在内部实现上不允许修改其元素值,从而使得代码更加安全。例如,调用函数时使用元组传递参数可以防止在函数中修改元组,而使用列表则很难保这一点。
    ,作为不可变序列,与整数、字符串一样,元组可用作字典的键,也可以作为集合的元素。而列表则永远都不能当作字典键使用,也不能作为集合中的元素,因为列表是可变的。内置函数hash()可以用来测试一个对象可哈希。一般来说,并不需要关心该函数的返回值具体是什么,重点是对象可哈希,如果对象不可哈希会抛出异常。>>>hash((1,))#元组、数字、字符串都是可哈希的3430019387558>>>hash(3)3>>>hash(''helloworld.'')-4012655148192931880>>>hash(\\\\[1,2\\\\])#列表不可哈希TypeError:unhashabletype:''list''3..生成器推导式生成器推导式也称为生成器表达式(generatorexpression),用法与列表推导式相似,在形式上生成器推导式使用圆括号(parentheses)作为定界符,而不是列表推导式所使用的方括号(squarebrackets)。与列表推导式的不同是,生成器推导式的结果是一个生成器对象。生成器对象类似于迭代器对象,具有惰求值的特点,只在需要时生成新元素,比列表推导式具有更高的效率,空间占用少,尤其适合大数据处理的场合。
    使用生成器对象的元素时,可以将其转化为列表或元组,也可以使用生成器对象的__next__()方法或者内置函数next()进行遍历,或者直接使用for循环来遍历其中的元素。但是不管用哪种形式,只能从前往后正向访问其中的元素,没有任何方法可以再次访问已访问过的元素,也不支持使用下标访问其中的元素。当所有元素访问结束以后,如果需要重新访问其中的元素,必须重新创建该生成器对象。enumerate、filter、map、zip等对象也有同样的特点。,包含yield语句的函数也可以用来创建生成器对象,详见第5章。>>>g=((i+2)2foriinrange(10))#创建生成器对象>>>gat0x0000000003095200>>>>tuple(g)#将生成器对象转换为元组(4,9,16,25,36,49,64,81,100,121)>>>list(g)#生成器对象已遍历结束,没有元素了\\\\[\\\\]>>>g=((i+2)2foriinrange(10))#重新创建生成器对象>>>g.__next__()#使用生成器对象的__next__()方法获取元素4>>>g.__next__()#获取下一个元素9>>>next(g)#使用函数next()获取生成器对象中的元素16

    售后保障

    最近浏览

    猜你喜欢

    该商品在当前城市正在进行 促销

    注:参加抢购将不再享受其他优惠活动

    x
    您已成功将商品加入收藏夹

    查看我的收藏夹

    确定

    非常抱歉,您前期未参加预订活动,
    无法支付尾款哦!

    关闭

    抱歉,您暂无任性付资格

    此时为正式期SUPER会员专享抢购期,普通会员暂不可抢购