迭代器:初探
上一章曾经提到过,其实for循环是可用于任何可迭代的对象上的。实际上,对Python中所有会从左至右扫描对象的迭代工具而言都是如此,这些迭代工具包括了for循环、列表解析、in成员关系测试以及map内置函数等。
"可迭代对象"的概念在Python中是相当新颖的,基本这就是序列观念的通用化:如果对象时实际保存的序列,或者可以再迭代工具环境中一次产生一个结果的对象,那就看做是可迭代的。
文件迭代器
作为内置数据类型的文件也是可迭代的,它有一个名为next的方法,每次调用时,就会返回文件中的下一行。当到达文件末尾时,next会引发内置的StopIteration异常,而不是返回空字符串。
这个接口就是Python中所谓的迭代协议:有next方法的对象会前进到下一个结果,而在一系列结果的末尾时,则会引发StopIteration。任何这类对象都认为是可迭代的。任何这类对象也能以for循环或其他迭代工具遍历,因为所有迭代工具内部工作起来都是在每次迭代中调用next,并且捕捉StopIteratin异常来确定何时离开。
for line in open('script.py'):
print(line.upper(),end='')
上面的代码就是文件迭代的一个例子,并且这种用法是最高效的文件读取方法,主要有三个优点:这是最简单的写法,运行快,并且从内存使用情况来说也是最好的。
替代的写法是:
for line in open('script.py').readlines():
print(line.upper(),end='')
这种调用方法会把文件一次性读到内存中,如果文件太大,那么内存会被消耗光的。
手动迭代:iter和next
为了支持手动迭代代码(用较少的录入),Python3.0还提供了一个内置函数next,它会自动调用一个对象的next方法。给定一个对象X,调用next(X)等同于X.next(),但前者简单很多。
从技术角度来讲,迭代协议还有一点值得注意。当for循环开始时,会通过它传给iter内置函数,以便从可迭代对象中获得一个迭代器,返回的对象含有需要的next方法。调用iter的步骤对于文件来说不是必须的,因为文件对象就是自己的迭代器,但是对于其他的一些内置数据类型来说,就不一定了。
列表以及很多其他的内置对象,不是自身的迭代器,因为它们支持多次打开迭代器。对这样的对象,我们必须调用iter来启动迭代:
L=[1,2,3]
iter(L) is L #return false
L.__next__() #会报错
I = iter(L)
I.__next__()
I.__next__()
虽然Python迭代工具自动调用这些(iter,next)函数,我们也可以使用它们来手动地应用迭代协议。
列表解析:初探
列表解析基础知识
L=[1,2,3,4,5]
L = [x+10 for x in L]
列表解析写在一个方括号中,因为它们最终是构建一个新的列表的一种方式。它们以我们所组成的一个任意的表达式开始,该表达式使用我们所组成的一个循环变量(x+10)。这后面跟着我们现在应该看作是一个for循环头部的部分,它申明了循环变量,以及一个可迭代对象(for x in L)
要运行该表达式,Python在解释器内部执行一个遍历L的迭代,按照顺序把x赋给每个元素,并且收集对各元素运行左边的表达式的结果。我们得到的结果列表就是列表解析所表达的内容――针对L中的每个x,包含了x+10的一个新列表。
其实列表解析式并不是必须的,因为它能完成的工作都能够通过for循环完成,但是列表解析式比手动的for循环语句运行得更快(往往速度快一倍),因为它们的迭代在解释器内部是以C语言的速度执行的,而不是以手动的Python代码执行的,特别是对于较大的数据集合,这是使用列表解析的一个主要的性能优点。
当我们考虑在一个序列中的每个项上执行一个操作时,都可以考虑使用列表解析。
扩展的列表解析语法
实际上,列表解析可以有更高级的应用。作为一个特别有用的扩展,表达式中嵌套的for循环可以有一个相关的if子句,来过滤那些测试不为真的结果项。
lines = [line.rstrip() for line in open('script.py') if line[0]='p']
这条if子句检查从文件读取的每一行,看它的第一个字符是否是p;如果不是,从结果列表中省略改行。
事实上,如果我们愿意的话,列表解析可以变得更加复杂――它们的完整语法允许任意数目的for子句,每个子句有一个可选的相关的if子句。
Python3.0中的新的可迭代对象
Pyton3.0中的一个基本的改变是,它比Python2.x更强调迭代。除了与文件和字典这样的内置类型相关的迭代,字典方法keys、values和items都在Python3.0中返回可迭代对象。 返回一个可迭代对象而不是返回一个结果列表的好处在于节省了内存的空间。
多个迭代器VS单个迭代器
多个迭代器:在它们的结果中能保持不同位置的多个迭代器
单个迭代器:只能保持一个迭代器,在遍历其结果之后,它们就用尽了。
通常通过针对iter调用返回一个新的对象,来支持多个迭代器;单个迭代器一般意味着一个对象返回其自身。
字典视图迭代器
在Python3.0中,字典的keys、values和items方法返回可迭代的视图对象,它们一次产生一个结果项,而不是在内存中一次产生全部结果列表。视图项保持和字典中的那些项相同的物理顺序,并且反映对底层的字典做出的修改。
和所有迭代器一样,我们总可以通过把一个Python3.0字典视图传递到list内置函数中,从而强制构建一个真正的列表。然而,这通常不是必须的。
此外,Python3.0字典仍然有自己的迭代器,它返回连续的键。因此,无需直接在此环境中调用keys:
for key in D:print(key,end='')
列表解析与map
列表解析在一个序列上的值应用一个任意表达式,将其结果搜集到一个新的列表中并返回。从语法上说,列表解析是由方括号封装起来的(为了提醒你它们构造了一个列表)。它们的简单形式是在方括号中编写一个表达式,Python之后将这个表达式的应用循环中每次迭代的结果搜集起来。例如,假如我们希望搜集字符串中的所有字符的ASCII码,可以这样做:
#循环的方法
res=[]
for x in 'spam':
res.append(ord(x))
#map函数的方法
res=list(map(ord,'spam'))
#列表解析
res=[ord(x) for x in 'spam']
增加测试和嵌套循环
其实,列表解析还要比上面说的通用的多,我们可以在for之后编写一个if分支,用来增加选择逻辑。
#列表解析
[x ** 2 for x in range(10) if x % 2 == 0]
#map
list(map((lambda x:x**2),filter((lambda x: x % 2==0),range(10))))
上述的两行代码都是搜集了0~9中的偶数的平方和,可以很明显的看到,完成同样的功能,列表解析的语句简单地多。
实际上,列表解析还能够更加通用。你可以在一个列表解析中编写任意数量的嵌套的for循环,并且每一个都有可选的关联的if测试。通用结构如下所示:
expression for target1 in iterable1 [if comdition1]
for target2 in iterable2 [if condition2] ...
for targetN in iterableN [if conditionN]
当for分句嵌套在列表解析中时,它们工作起来就像等效的嵌套的for循环语句。例如,如下的代码:
res=[x+y for x in [0,1,2] for y in [100,200,300]]
与下面如此冗长的代码有相同的效果:
res=[]
for x in [0,1,2]:
for y in [100,200,30]:
res.append(x+y)
列表解析和矩阵
使用Python编写矩阵的一个基本的方法就是使用嵌套的列表结构,例如,下面的代码定义了两个3x3的矩阵:
M=[[1,2,3],
[4,5,6],
[7,8,9]]
N=[[2,2,2],
[3,3,3],
[4,4,4]]
列表解析也是处理这样结构的强大工具,它们能够自动扫描行和列。
取出第二列的所有元素:
[row[1] for row in M] #[2,5,8]
[M[row][1] for row in (0,1,2)] #[2,5,8]
取出对角线上的元素:
[M[i][i] for i in range(len(M))] #[1,5,9]
混合多个矩阵,下面的代码创建了一个单层的列表,其中包含了矩阵对元素的乘积。
复制代码 代码如下:
[M[row][col] * N[row][col] for row in range(3) for col in range(3)] #[2,4,6,12,15,18,28,32,36]
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。