【背景】:
国庆期间没有出去看人海,基于看过的各位大佬的文章想着深挖整理下关于for循环。
【前言】:
想要遍历集合中的每一个元素并进行处理,首先想到的应该就是for循环了。每遍历一个元素就赋值给到i,那么关于for循环的实现具体是怎么样的呢?
# for循环语法
for i in 可迭代对象:
循环代码
print("---------------------------------")
# 例1:
for i in range(10):
print(i)
#例2:
list1 = [1, 2, 3, 4]
for i in list1:
print(i)
for循环实现:
1.实现循环时,会首先将在in后面可迭代对象调用内置方法__iter__()返回迭代器对象;
2.调用迭代器的内置方法__next__()返回可迭代对象的元素来实现迭代
3.捕捉到stopIteration异常后,退出循环
【概念介绍】:
1.迭代(Iteration)
定义:在python中迭代就是对可迭代对象/序列中每个元素依次重复执行操作的过程,通过循环来实现对集合中的每个元素进行处理
常见的迭代方式:
for循环
while循环
迭代的好处:可以高效地处理大量数据和重复性任务,减少代码冗余
迭代的注意点:需要注意循环体/终止条件的逻辑是正确的,否则会进入死循环
2.可迭代对象(Iterable)
1. 定义:一组元素的集合/序列
2.可迭代对象实现原理:包含内置方法:
__iter__(),该方法返回迭代器对象
3.常见的可迭代对象(列举已知的):
数据类型: 列表,元组,字典(key), 字符串,集合
函数:range(),list(),dict(),str(),tuple()
其他:文件对象
3.迭代器(Iterator) (又被称为游标)
1.定义:提供访问可迭代对象每个元素的接口,指向可迭代对象的当前元素,实现迭代器协议
2.迭代器的实现原理是:包含2个核心方法
__iter__(): 返回迭代器对象
__next__():每次调用返回可迭代对象中的下一个元素,若无则抛异常stopIteration
3.如何将可迭代对象变成迭代器对象?
1. 使用内置方法__iter__()
list1 = [1,2,3]
list_iterator = list1.__iter__()
2.使用内置函数iter()
list1 = [1,2,3]
list_iterator = iter(list1)
4.迭代器的特点
1.惰性计算。需要时才会生成和返回下一个元素,非一次性计算并存储
2.单向性。只可向前遍历,不能后退/重复访问已遍历过的元素
lst = [1,2,3]
for i in lst:
lst.remove(i)
lst.append(i)
print(lst) # [2,1,3]
3.可迭代对象。迭代器本身是一个可迭代对象,有内置方法__iter__()
4.低级别接口:允许用户按需获取元素,控制迭代过程并在必要时处理异常
5.一次性消耗,每个迭代器只能遍历一次可迭代对象中的元素
5.常见的迭代器(列出已知的)
- 文件对象
- 生成器
4. 判断是否为可迭代对象,迭代器?
使用内置函数:isInstance(object,type)
可迭代对象:
from collections.abc import Iterable
isInstance(object,Iterable)
迭代器:
isinstance(object,iterator)
5.函数/方法参数是可迭代对象的
-
enumerate(iterable)将可迭代对象的索引和值打包成一个个元组
-
例1:将打包的元组转换为列表 list1 = [1, 2, 3] l = list(enumerate(list1)) print(l) 例2: 遍历 list1 = [1,2,3,4] for i,j in enumerate(list1): print(f"列表的第{i+1}个元素的值是{j}") 或者 list1 = [1,2,3,4] for i in enumerate(list1): print(f"列表的第{i[0]+1}个元素的值是{i[1]}")
-
-
zip(iterable1,,,) 将多个可迭代对象打包成一个个元组
- 可迭代对象的元素长度相同
-
场景1:创建2个长度为10的列表 其中内容均为正整数,要求输出所有相同的数字以及相同数字对数 list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0] list2 = [2, 2, 3, 5, 6, 6, 7, 8, 1, 9] list3 = [(i, j)for i, j in zip(list1, list2) if i == j] print(f"相同的数字是{list3},对数是{len(list3)}对") # 相同的数字是[(2, 2), (3, 3), (6, 6), (7, 7), (8, 8)],对数是5对 场景2: 转置矩阵 lst = [[8,9,10],[11,12,12]] print(list(map(list,zip(*lst))))
-
- 可迭代对象的元素长度不同,则最终生成的元组个数是以长度较短的为准.举例:
- list1=[1,2,3,4]
- tup1=('hello','world')
- zipobj = list(zip(list1,tup1)) # [(1,'hello),(2,'world')]
- 可以结合list(),dict(),tuple()将一个个元组以列表,字典,元组形式返回
- 可迭代对象的元素长度相同
-
Counter类 参数可以是可迭代对象,
- 类counter(iterable) 记录可迭代对象元素的次数,以字典形式返回
-
场景1: 2个单词是否为变位词即字母以及字母数量相同 from collections import Counter def word1(str1,str2): return Counter(str1)==Counter(str2) print(word1("taste","state")) # True
- 类的方法如下:
- most_common([n]), 以单个元素是元组,整体是列表形式返回次数最多的n个元素和它们的次数
-
from collections import Counter c = Counter(['a', 'b', 'c', 'd', 'e', 'a']) c1 = c.most_common(1) # [('a', 2)] print(c1) c2 = c.most_common() # [('a', 2), ('b', 1), ('c', 1), ('d', 1), ('e', 1)] print(c2)
-
all(iterable)
- 所有元素为True即则返回True,否则返回False
-
a = [-2,2,-3,0] print(all([x >0 for i in a])) # False b = [1,2,3,4] print(all([x >0 for i in b])) # True
-
- 特别注意的:如果iterable为空,则返回True
-
a = [] print(all(a)) # True
-
- 所有元素为True即则返回True,否则返回False
-
any(iterable)
- 存在元素是True,则返回True
-
a = [-2,2,-3,0] print(any([i >0 for i in a])) # True b = [-1,-2,-3,-4] print(any([i >0 for i in b])) # False 题目一: 求密码安全等级 # 分数与密码安全等级的字典并输出 # 题目:密码长度10位以及以上,可以为数字,大小写字母,标点符号,有其中一项则加1分 # 安全等级:弱,较弱,中,较强,强 import string n_dict = {1: "弱", 2: "较弱", 3: "中", 4: "较强", 5: "强"} def passwd(n_str): score = 0 if any(char.isdigit() for char in n_str): score += 1 if any(char.isupper() for char in n_str): score += 1 if any(char.islower() for char in n_str): score += 1 special_char = "+-/_*&%^@" if any(char in special_char for char in n_str): score += 1 if score not in n_dict: return "未知" else: return f"密码的分数是{score},对应的密码安全等级是{n_dict[score]}" print(passwd("900507Ha"))
-
- 特别注意的:如果iterable为空,则返回False(目前本人还有疑惑)
-
a = [] print(any(a)) # False
-
- 存在元素是True,则返回True
-
sum(iterable[,start])
- 初始化值start以及可迭代对象每个元素进行相加
- 注意:不可嵌套列表,否则报错TypeError: unsupported operand type(s) for +: ‘int‘ and ‘list‘,因为sum是按照第一层元素相加的
- 默认start=0
- 注意:可迭代对象元素数据类型需要是int
-
无参数start,求1-100的加和 print(sum((i for in range(1,101)))) # 5050 print(sum((False,6)) # 6 print(sum((True,6)) # 7 有参数start print(sum([1, 2, 3], 1)) # 1+1+2+3=7
- 初始化值start以及可迭代对象每个元素进行相加
-
combinations(iterable,r)
-
指定长度,抽样不重复组合,返回一个个元组组成的列表
-
抽取1,2,3三个元素内不重复的2位数 from itertools import combinations list1 = [i for i in combinations([1, 2, 3], 2)] print(list1) # [(1, 2), (1, 3), (2, 3)]
-
-
max(iterable[,key=函数的内存地址/方法的内存地址])同理min()
- 可迭代对象元素的大小,如果有key参数,则是将key对应的返回值作为比较依据
-
场景1: 求列表中最频繁出现的元素,指定自定义比较规则 lst = [1,2,3,4,2,2,3,1,2,4,2,4] print(max(set(lst),key=lst.count)) # 2 场景2: 默认比较可迭代对象元素的大小 lst = [1,2,3,4] print(max(lst)) # 4
-
- 可迭代对象元素的大小,如果有key参数,则是将key对应的返回值作为比较依据
-
len(iterable)
- 计算可迭代对象元素的长度
-
1.字符串 str = "hello" print(len(str)) # 5 2.列表 lst = [1, 2, 3, 4, 5] print(len(lst)) # 5 3.集合 set_1 = {1, 2, 3, 4, 5} print(len(set_1)) # 5 4.元组 tup = (1,2,3,4,5) print(len(tup)) # 5 5.字典 dict_1 = {'a': 1, 'b': 2, 'c': 4} print(len(dict_1)) # 3 6.其他可迭代对象 num = range(0, 5) print(len(num)) # 5
6. 可迭代对象特性:
- 支持自动解包
- 解包即将可迭代对象元素一一解开
- 接收变量的个数需要<=被解包的对象
- 对于变量个数不确定的,可以使用*可变长度变量接收多个元素;**可变长度变量接收键值对元素
-
# n指向range(3)的内存地址 n = range(3) # *代表多个变量值,将range(3)解包元素:0 1 2 n1 = {*n} # {0,1,2}
7.总结:可迭代对象和迭代器
1. 可迭代对象调用__iter__()方法/iter()变成迭代器-》迭代器可以对可迭代对象使用__next__()才可以进行迭代
2.迭代器本身也是可迭代对象,但可迭代对象不一定是迭代器
参考链接: 【Python】可迭代对象与迭代器_python enumerate是可迭代对象_小糊^的博客-CSDN博客python基础 — 可迭代对象,迭代器和生成器_python判断是否是迭代器_笃行之.kiss的博客-CSDN博客