python迭代代码,python语言编程中迭代器
Yyds干货库存
最后一节以或多或少的悬念结束。
我们在Python中发现了循环和迭代器,并体验了它们提供的一些潜力。
"您遗漏了zip()和enumerate(),这两个函数对于任何关于迭代器的讨论都是非常重要的!"是的,它们当然重要,所以这篇文章有点长。但是,不要怕——。接下来,我们将学习和理解它们,揭开其中的奥秘,甚至更多!
顺便说一句,如果你还没有读过上一节“循环和迭代器”,那么你现在就想回去看看!别担心,我会等你的。
将整篇文章都献给几个内置函数似乎很奇怪,但是它们为Python贡献了很多魔力。
Range还记得上一篇文章中的函数range()吗?我们简单介绍了如何用它生成数字序列,但它的功能比乍一看强大得多。
使用带有start和stop的range()的第一个重要点是理解参数:range(start,stop)。start是指我们从起始数开始计数,包括数字start;停止是指我们到达停止数后停止计数,但不包括停止数!
所以,如果我们有range(1,10),我们将得到[1,2,3,4,5,6,7,8,9]。从1点开始,但不是10点。
如果我们想在序列中包含10,我们需要range (1,11): [1,2,3,4,5,6,7,8,9,10]。
顺便说一下,如果我们只指定了一个参数,比如range(10),它会假设范围的起点是0。在这种情况下,我们将得到[0,1,2,3,4,5,6,7,8,9]。当range()被用来控制传统的for循环时,你会经常看到它被这样使用。
我最喜欢的step的技巧是它可选的第三个参数:当你指定range(start,stop,step)时,这个step参数允许你每次增加大于1的值。
可用于实现打印出7的前100的所有倍数,从7本身到700,包括700:range(7,701,7)会做到这一点。(请注意,我在最后指定了701,以确保包含700。)
它还可以用来打印所有小于100的奇数:range(1,100,2)。
Return如果您尝试使用range并打印出所有7的倍数,您可能会注意到结果不符合您的预期:
七=范围(7,701,7)
打印(七)
命令print打印文本短语范围(7,701,7)。发现不是我们想要的!
记住range()返回一个类似迭代器的对象(python 2x返回一个列表)。为了将它完全存储为一个列表,我们需要通过将它包装在函数list()中将其转换为一个列表:
sevens=list(范围(7,701,7))
打印(七)
现在输出的是我们想要的——的前100个7的倍数的列表!
在我们深入了解分段的所有这些新的迭代优势之前,我想向您介绍一下扩展索引符号,它使我们能够更有力地从有序容器(如列表)中选择元素。
说到列表,请看以下内容:
档案=[邪恶爵士,贝尔加博士,格林尼特男爵,梅德娃,大混乱将军,布格斯扎帕,杰奎琳海德,简反应,迪加密]
不管你是否意识到,你已经知道了正常的索引符号。
打印(档案[1])
贝尔加博士
这将返回容器的第二个元素(索引1)。档案很简单,对吧?几乎所有的语言都提供这种行为。
那么,如果我们想要第二个和第三个元素呢?
打印(档案[1:3])
[贝尔加博士,格林尼特男爵]
刚刚发生了什么?在扩展索引符号中,我们有三个用冒号分隔的参数:start、stop和step。嘿,看起来很眼熟,对吧?这些是range()使用的相同参数!它们也以完全相同的方式工作。(当然,我们在上面的例子中省略了第三个参数【step】。)
注意,这个例子打印出了Dr. Belljar(索引1)和Baron Grinnit(索引2),但不是Medeva,因为stop参数被强制停止。
小心,开始一定要少于停止,才能有结果!但是有一个例外,我们后面会讲到。
现在,如果您想要第二个中的所有其他元素呢?
打印(档案[1:2])
[贝尔加博士,梅德娃,布格斯扎珀,简反应]
您会注意到我们没有指定stop。因为我们真的不需要!索引符号允许您省略任何参数,只要您用冒号来分隔它。由于第二个参数被省略了,我们只是在它原来的位置后面加上了额外的:
反向分割扩展索引符号将(开始、停止、步进)逻辑向前推进了一步,允许您反向分割!一开始有点混乱,但是请坚持住.
打印(档案[-1])
打印出列表中的最后一项。负数代表从列表末尾开始计数!这感觉有点奇怪,因为我们习惯于从0指数开始计数,但是负零其实并不是一个有意义的数字,所以我们从-1开始。
有鉴于此,我们如何打印最后三项呢?我们可能会尝试这样做,但它实际上不起作用。
打印(档案[-1:-4])
[]
这将返回一个空列表。为什么?请记住,start必须小于stop,即使使用了负索引。所以,我们必须以-4为起点,因为-4 -1。
打印(档案[-4:-1])
[Buggs Zapper ,杰奎琳海德,简反应]
这样更近了,但还是有问题。Dee Cryption是我们的最后一个元素,它在哪里?记住,stop是停止计数的数字,不包含当前数字。但是我们不能只使用档案[-4],因为那只会给我们Buggs Zapper。和档案[-4:-0]无效。
这个问题的解决方案是告诉Python我们显式省略了第二个参数:在我们的第一个参数后面加一个冒号!
打印(档案[-4:])
[Buggs Zapper , Jacqueline Hyde , Jane Reaction , Dee Cryption]
现在我们有了最后一个元素。如果我们想要最后三个,那么把-4改成-3。
打印(档案[-3:])
[杰奎琳海德,简反应,迪神秘]
如果我们在第三个参数步骤中输入一个负数,你认为会发生什么?让我们试试-1,它前面有两个冒号,表示我们需要整个列表。
打印(档案[:-1])
[ Dee cryptic , Jane Reaction , Jacqueline Hyde , Buggs Zapper , General Mayhem , Medeva , Baron Grinnit , Belljar博士, Vile爵士]
看起来像是反印所有东西,除了!事实上,将step设置为-1会颠倒列表。
现在让我们试试-2.
打印(档案[:-2])
[迪克里芬,杰奎琳海德,大混乱,格林尼特男爵,邪恶爵士]
这不仅颠倒了列表,还跳过了所有元素。负步骤行为与正步骤完全相同,只是它是反向工作的!
那么,如果我们想把所有的东西放在一起呢?也许我们想把第二、第三和第四个元素倒着列出来。
打印(档案[2:5:-1])
[]
注意:必须按顺序遍历起点和终点。如果步长为正,则开始必须小于停止;但是,如果步长为负值,则start必须大于stop!
你可以把它想象成一条摄影之旅的步行路线。Step告诉你走哪条路,你的步幅应该是多大。一到就开始拍照,一遇到问题就停下来把相机收起来。
所以,要解决这个问题,我们需要交换我们的起点和终点。
打印(档案[5:2:-1])
[Buggs Zapper , Mayhem将军, Medeva]
说明:Python还提供了slice()和itertools.islice()函数,它们的行为方式大致相同。但是,它们比扩展索引符号更受限制,所以您最好使用扩展索引符号,而不是函数。
操纵迭代对象我们将在这一节中探讨的其余函数都与迭代对象一起使用。尽管在大多数例子中我将使用列表,但是请记住,您可以使用任何可迭代的对象,包括range()函数。
假设您在一个迭代容器(比如一个列表)中获得了大量数据,比如一个包含数百个名称的列表。在将这个列表输入到您的超级算法之前,您希望通过检查每个元素中是否有异常值来节省一些处理时间。
这就是all函数的用途。
档案=[邪恶爵士,贝尔加博士,格林尼特男爵,梅德娃,大混乱将军,布格斯扎帕,,简反应,迪克里芬]
打印(所有(档案))
错误的
您可能还记得,在Python中,空字符串(“”)的计算结果为False。all()函数评估每个元素并确保它返回True。即使计算结果为false,all()函数也会返回False。
Any()的工作方式几乎相同,但它只需要一个元素就可以计算True。
乍一看,这些似乎不是很有用,但是当与一些其他工具结合使用,甚至与列表解析(后面的部分)结合使用时,它们可以节省大量时间!
枚举在循环中。如果需要访问列表的值和索引,可以使用enumerate()函数来完成。
foo=[A , B , C , D , E]
对于索引,枚举(foo)中的值:
print(fElement {index}的值为{value}。)
但是enumerate()并不局限于列表。像所有这些其他函数一样,它适用于任何可以迭代并且需要返回数字(或枚举)的每个值的对象。例如,我们在range()中使用它。让我们用它来打印从10到100的每一个10的倍数(范围(10,101,10))。下面是一个例子.
对于索引,枚举中的值(范围(10,101,10)):
print(fElement {index}的值为{value}。)
这给了我们.
元素0的值为10。
元素1的值为20。
元素2的值为30。
元素3的值为40。
元素4的值为50。
元素5的值为60。
元素6的值为70。
元素7的值为80。
元素8的值为90。
元素9的值为100
我们可以从中得出一个简洁的模式,但是我们要从1开始枚举,而不是从0。果然,我们可以通过将起始计数作为第二个参数来进行传递。我们还将稍微调整我们的输出信息,并简化输出格式。
对于索引,枚举中的值(范围(10,101,10),1):
print(f { index }乘以10等于{value} )
当我们运行它时,我们得到.
1乘以10等于10
10乘以2等于20
3乘以10等于30
4乘以10等于40
五乘以十等于五十
六乘以十等于六十
七乘以十等于七十
八乘以十等于八十
九乘以十等于九十
十乘以十等于一百
假设我们正在跟踪在一堆地方发现的线索的数量,并将它们存储在字典中。对于这个例子,我将在最后一节借用并调整字典。
位置={
阅兵场:0,
Ste。-凯瑟琳街:0,
维多利亚桥:0,
地下城:3,
皇家公园山:0,
美术馆:0,
《幽默名人堂》:2、
拉钦运河:4,
蒙特利尔爵士音乐节:1,
奥林匹克体育场:0,
圣劳伦斯河:2,
旧蒙特利尔:0,
麦吉尔大学:0,
木屋了望台:0,
圣母院:0
}
也许我们需要找到所有有线索的地方,忽略其余的。我们将首先编写一个函数来测试一个特定的键值元组对。这似乎是一个荒谬的过度复杂化,但它会很有用:
定义有_线索(对):
返回布尔值(对[1])
将我们字典中的每一对作为元组提交给函数,pair[1]将是值(例如,(地下城,3))。如果线索号为0,bool()函数将返回False,那么所有其他为True的元素就是我们想要的。
我们使用filter()来缩小刚刚编写的函数的字典范围。回想一下上一节,我们需要使用locations.items()来获得成对的键和值。
对于地点,过滤器中的线索(has_clues,locations.items()):
打印(地点)
请注意,我们不包括has_clues后面的括号。我们将实际函数作为对象传递!过滤器将被实际调用。
果然,运行这段代码将打印出我们有线索的五个地方(值为0).
地下城
幽默名人堂
拉钦运河
蒙特利尔爵士音乐节
圣劳伦斯河
在本系列的后面部分,我们将学习lambdas匿名函数,我们不必单独定义函数。代码如下所示.
对于place,filter(lambda x:bool(x[1]),locations.items())中的线索:
打印(地点)
map()函数类似于filter(),只是它不是使用函数来省略iterable对象中的元素,而是用来更改它们。
假设我们有一个华氏温度列表:
温度=[67.0,72.5,71.3,78.4,62.1,80.6]
我们想把所有这些都转换成摄氏度,所以我们为此写了一个函数。
定义温度:
返回回合((温度- 32)/1.8,1)
我们可以使用这个map()函数将它应用于temps中的每个值,从而生成可以在循环中(或任何地方)使用的迭代器。
对于map中的c(f _ to _ c,温度):
打印(f { C } C )
记住,我们把函数对象f_to_c作为map()的第一个参数传递,所以去掉了括号!
运行循环输出:
19.4摄氏度
22.5摄氏度
21.8摄氏度
25.8摄氏度
16.7摄氏度
27.0摄氏度
和最小最大值。让我们继续使用刚才的温度列表示例。如果我们想找到列表中的最低值或最高值,我们可以分别使用min()或max()函数。这不是什么新鲜事。
温度=[67.0,72.5,71.3,78.4,62.1,80.6]
打印(最低温度)
62.1
打印(最高温度)
80.6
注意:不管iterable对象是什么,您也可以使用这些函数在您提供的参数列表中查找最小或最大的参数,例如min(4,5,6,7,8),它将返回4。
通常,你需要对可迭代对象进行排序。这是通过Python sorted()内置函数非常有效地完成的。
温度=[67.0,72.5,71.3,78.4,62.1,80.6]
对于排序中的t(温度):
印刷(吨)
输出如下.
62.1
67.0
71.3
72.5
78.4
80.6
在大多数情况下,扩展索引符号[:-1]将允许您反转列表或其他有序迭代。但如果这不是唯一的方法,还可以使用reversed()函数来反转。
比如我用sorted()和刚才的函数结合。
温度=[67.0,72.5,71.3,78.4,62.1,80.6]
对于反转的t(排序(温度)):
印刷(吨)
程序输出如下.
80.6
78.4
72.5
71.3
67.0
62.1
sum的另一个快速内置函数是sum(),它将迭代中的所有元素加在一起。当然,这只有在所有元素都可以相加的情况下才有效。
这样做的一个用途是更早地找到这些温度的平均值。您可能还记得len()函数告诉我们容器中有多少元素。
温度=[67.0,72.5,71.3,78.4,62.1,80.6]
平均值=总和(温度)/长度(温度)
打印(圆形(平均值,2))
71.98
Zip,还记得前面那个关于地点和线索的例子吗?假设我们得到的信息不在字典里,而是在两个列表里:
位置=[阅兵场, Ste。-“凯瑟琳街”、“维多利亚桥”、“地下城”、“蒙特皇家公园”、“美术博物馆”、“幽默名人堂”、“拉钦运河”、“蒙特利尔爵士音乐节”、“奥林匹克体育场”、“圣劳伦斯河”、“旧蒙特利尔”、“麦吉尔大学”、“木屋了望台”、“圣母教堂”]
线索=[0,0,0,3,0,0,2,4,1,0,2,0,0,0,0]
那么just方法是无法实现搜索的,但是现实世界中确实存在我们会通过这种方式获取数据的场景。
幸运的是,zip()函数可以帮助我们处理这些数据,使用迭代器将它们聚合成元组,给我们(locations [0],clusters [0]),(locations [1],clusters [1]),(locations [2],clusters [2])等等。
zip()函数甚至不限于两次迭代;可以尽量压缩在一起!如果迭代的长度不同,那么“额外”的内容将放在最后。
当然,在这种情况下,两个列表具有相同的长度,因此结果相当明显。让我们使用zip中的数据创建一个新列表,并将其打印出来。
数据=列表(zip(位置、线索))
打印(数据)
这给了我们一个不同于之前从字典函数中得到的结构。items()!
[(阅兵场,0),( Ste。-凯瑟琳街,0)、(维多利亚桥,0)、(地下城,3)、(蒙特皇家公园,0)、(美术博物馆,0)、(幽默名人堂,2)、(拉钦运河,4)、(蒙特利尔爵士音乐节,1)、(奥林匹克体育场,0)、(圣劳伦斯河,2)、(老蒙特利尔,0)、(麦吉尔大学,0)、(夏莱了望,0)、(圣母院,0)]
事实上,如果我回忆一下我的filter()的lambda函数,我可以调整它来使用zip,让我们完全从两个列表开始工作:
对于地点,过滤器中的线索(lambda x:bool(x[1]),zip(locations,clues)):
打印(地点)
和以前一样,输出.
地下城
幽默名人堂
拉钦运河
蒙特利尔爵士音乐节
圣劳伦斯河
Itertools我已经介绍了几乎所有用于处理iterable对象的Python内置函数,但是在itertools模块中还有更多。我强烈建议阅读官方文件以获取更多信息。
与本系列的其他部分相比,这一部分的总结更具有百科全书的性质,但是我希望它能让您了解一些不可思议的事情,这些事情可以通过新的迭代器技巧来完成。
如果你还在等前面提到的生成器表达式和列表解析,不要着急!它们将出现在下一节。
原创作品来自程,
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。