一 可迭代对象,迭代器和生成器
可迭代对象 | 迭代器 | 生成器 | |
定义 |
可迭代 (Iterable):指某个容器类型数据可被for循环遍历获取内部所有成员。那么这个类型数据就称之为可迭代。 对象:也叫实例(Instance),可以理解为是一个记录和管理数据的容器,它的成员是属性(变量,属性的值就是数据)和方法(method, 就是操作该对象以及对象内部数据的函数)。 从使用角度来说,能被for循环遍历输出内部每一个成员的都是可迭代对象。 从语法形式来说,能调用 |
|
生成器是一个特殊迭代器,也是一个特殊函数,内部可以有1个或多个yield关键。 |
实例 |
判断一个数据是否是可迭代对象 set_data = {'a',2,'c','b'} |
set_data = {"A", "B", "D", 100} # 迭代器中所有值都被提取完成后,再次取值,python会以抛出一个StopIteration异常告诉我们,没有值了。这并不代表错误发生,而是一种迭代完成的标志,防止出现无限循环。 # |
"""生成器的声明""" # for item in g1: 因为这个生成器会记录和保存程序执行的状态,因此,当生成器结束了以后,就不会再逆向取值,所以下面的代码拿不到数据的,因此上面已经取完了 # 每次调用生成器函数,都会产生一个新的生成器对象。 |
比较 | 优点:
缺点:
|
优点:
缺点:
|
同迭代器。生成器中yield关键字的特征是暂停函数执行 |
关系 |
可迭代对象包含了迭代器和生成器 |
注:
1 for循环的本质
x = 可迭代对象 # for循环的形式: for item in x: print(item)
区别于while循环模拟遍历过程(while比for循环要单调一点,仅仅是重复)
data = [10,20,30,40] # 1. 先执行iter方法,把可迭代对象转换成迭代器 iter_data = iter(data) while True: try: #异常处理语句,可以让我们识别代码异常而不会导致代码因为异常出错而终止 # 2. 每次循环,通过next取值,付给item item = next(iter_data) print(item) except StopIteration: break # 此处,退出循环
2 查看一个对象是否是可迭代对象或迭代器
from collections.abc import Iterable, Iterator data = [1, 2, 3, 4] print(isinstance(data, Iterable)) # True # 查看是不是可迭代对象 print(isinstance(data, Iterator)) # False # 查看是不是迭代器 # 在 python中容器数据类型都是可迭代对象,但是并非迭代器,那么我们就可以进行装换。[高阶函数(filter, map..)的返回值是一个迭代器]
# 方式1: print(isinstance(data.__iter__(), Iterator)) # True # 方式2: print(isinstance(iter(data), Iterator)) # True #isinstance 是面向对象里面的内容,表示判断当前变量是否属于某个类型。区别于type,用于基本函数类型
3 生成器实例补充
""" next 使用生成器过程中,仅仅只能接受yield暂停时返回的数据 send 使用生成器过程中,不仅可以接受yield暂停时返回的数据,还可以在send()的小括号把数据从外界传递到生成器函数内部(传参)给上一个yield(也就是暂停出)接收到 """ 1 def gen2(): key = 0 print(">>>>> 嘟嘟,开车了") while True: food = yield "第%s次" % key print(f"内部接收到了{food}") key += 1 # 判断当前文件是否作为主程序入口来运行, # 如果__name__魔术变量的值为"__main__"则表示当前文件是主执行文件 # 如果__name__魔术变量的值为文件名,则表示当前文件不是主执行文件 if __name__ == "__main__": g2 = gen2() # 在循环之前,先执行一遍send的作用是为了预激活生成器, # 让生成器内部执行到第一个yield位置,否则代码没有暂停的话,就无法通过send传递数据给内部的yield ret = g2.send(None) print(ret) for item in ["苹果","芒果"]: res = g2.send(item) print(f"res={res}") 输出: 嘟嘟,开车了 第0次 内部接收到了苹果 res=第1次 内部接收到了芒果 res=第2次 2 yield from可以将一个可迭代对象变成一个迭代器返回,也可以用于多个生成器之间进行嵌套调用 def gen1(): a = 0 while True: # print("+++++++") a = yield a**2 def gen2(gen): # a = 0 # while True: # # print("+++++++") # a = yield a ** 2 yield from gen # 相当于一次性声明了多个yield if __name__ == '__main__': g1 = gen1() g2 = gen2(g1) g2.send(None)#在一个生成器函数未启动之前,是不能传递数值进去。必须先传递一个None进去或者调用一次next()方法,才能进行传值操作 for i in range(5): # print(">>>> %s" % i) print(g2.send(i)) 输出:0 1 4 6 9 16
3 用生成器实现斐波那契 def fib(max): n, a, b = 0, 0, 1 # n表示当前第几项,a表示第一项的值,b表示第二项的值 while n <= max: yield a a, b = b, a + b n = n + 1 g1 = fib(10) for i in g1:#生成器为特殊的迭代器,可遍历可调用next方法 print(i)#输出a的值
# 0 1 1 2 3 5 8 13
二 推导式
推导式,实际上就是一种代码简写方式。是通过一行代码完成一个或多个循环和判断,并遍历出一系列数据的编写代码方式
语法:
成员 for 循环 ... if 判断 ...
推导式种类
其中,列表和字典最常用 # 1. 列表推导式,结果是一个列表 [item for item in Iterable] # 2. 字典推导式,结果是一个字典 {a:b for a,b in iterable.items()} # 3. 集合推导式,结果是一个集合 {item for item in Iterable} # 4. 生成器表达式,结果是一个生成器 (item for item in Iterable)
实例1 列"""
推导式里面可以存在1-多个for循环,也可以有0-多个判断, 但是判断和循环需要根据代码嵌套顺序来缩写 """ """1. 找出1~10之间的偶数""" # ret = [] # for num in range(1, 11): # if num % 2 == 0: # ret.append(num) # print(ret) # 上面的这种结构代码就可以使用推导式进行简写 # ret = [num for num in range(1, 11) if num % 2 == 0] # print(ret) 2 字典推导式 """1. 统计列表中各个字符出现的次数""" # data = ["A", "B", "C", "A", "C", "A"] # # ret = {} # # for item in data: # # ret[item] = data.count(item) # # 上面的这种结构代码就可以使用推导式进行简写 # ret = {item: data.count(item) for item in data} # print(ret) 3 集合推导式 """1. 计算列表中每个值的平方,自带去重功能""" # data = [1, -1, 2, -3, 3] # # ret = set() # # for num in data: # # ret.add(num**2) # 上面的这种结构代码就可以使用推导式进行简写 # ret = {num**2 for num in data} # print(ret) 4 生成器推导式 获取1-10整数的平方 """上面的代码实际上是以下代码的简写""" def gen(): for i in range(1, 11): yield i**2
n = gen()
for i in n: print(i)# 上面的这种结构代码就可以使用推导式进行简写 # ret = (i**2 for i in range(1, 11)) # print(ret)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构