【一】迭代器
【1】介绍
迭代器即用来迭代取值的工具,而迭代是重复反馈的过程的活动
其目的通常是为了逼近所需的目标或结果,每一次对过程的重复称为一次”迭代“
而每一次迭代得到的结果会作为下一次迭代的初始值,单纯的重复并不是迭代
while True: msg = input('>>: ').strip() print(msg) # 获取到返回值 num_list = [0, 1, 2, 3, 4, 5] count = 0 while count < len(num_list): # 每一次使用的索引位置就是上一次 +1 后的索引位置 print(num_list[count]) count += 1
【二】可迭代对象
【1】什么是可迭代对象
从语法上讲,内置有 __ iter __ 方法的对象都是可迭代对象
【2】八大基本数据类型
# 【1】数字类型 # 【1.1】整数类型 --- 不是 num = 1 print(num.__iter__) ''' Traceback (most recent call last): File "E:PythonProjects迭代器.py", line 10, inprint(num.__iter__) AttributeError: 'int' object has no attribute '__iter__'. Did you mean: '__str__'? ''' # 【1.2】浮点类型 --- 不是 num_float = 1.0 print(num_float.__iter__()) ''' Traceback (most recent call last): File "E:PythonProjects迭代器.py", line 20, in print(num_float.__iter__) AttributeError: 'float' object has no attribute '__iter__'. Did you mean: '__str__'? ''' # 【2】字符串类型 name = 'chosen' print(name.__iter__) # print(name.__iter__()) # # 【3】布尔类型 is_right = False print(is_right.__iter__) ''' Traceback (most recent call last): File "E:PythonProjects迭代器.py", line 37, in print(is_right.__iter__) AttributeError: 'bool' object has no attribute '__iter__'. Did you mean: '__str__'? ''' # 【4】列表类型 name_list = [1, 2, 3] print(name_list.__iter__) # print(name_list.__iter__()) # # 【5】字典类型 info_dict = {"name": "chosen"} print(info_dict.__iter__) # print(info_dict.__iter__()) # # 【6】元祖类型 num_tuple = (1,) print(num_tuple.__iter__) # print(num_tuple.__iter__()) # # 【7】集合类型 num_set = {1} print(num_set.__iter__) # print(num_set.__iter__()) #
【3】总结
非可迭代对象
整数类型
浮点类型
布尔类型
可迭代类型
字符串类型
列表类型
字典类型
元组类型
集合类型
【三】迭代器对象
【1】什么是迭代器对象
调用obj.__iter__()方法返回的结果就是一个迭代器对象(Iterator)。
迭代器对象是内置有 iter 和 next 方法的对象,打开的文件本身就是一个迭代器对象
执行迭代器对象.iter()方法得到的仍然是迭代器本身
而执行迭代器.next()方法就会计算出迭代器中的下一个值。
迭代器是Python提供的一种统一的、不依赖于索引的迭代取值方式,只要存在多个“值”,无论序列类型还是非序列类型都可以按照迭代器的方式取值
【2】八大基本数据类型
# 【1】字符串类型 name_str = 'chosen' name_iter = name_str.__iter__() name_iter_two = iter(name_str) print(name_iter) print(name_iter_two) ## print(name_iter.__next__()) # c print(next(name_iter)) # h # 【2】列表类型 name_list = [1, 2, 3] name_list_iter = iter(name_list) print(name_list_iter) # print(name_list_iter.__next__()) # 1 print(next(name_list_iter)) # 2 # 【3】字典类型 info_dict = {"name": "chosen", "age": 18} info_dict_iter = iter(info_dict) print(info_dict_iter) # print(info_dict_iter.__next__()) # name print(next(info_dict_iter)) # age # 【4】元祖类型 num_tuple = (1, 2) num_tuple_iter = iter(num_tuple) print(num_tuple_iter) # print(num_tuple_iter.__next__()) # 1 print(next(num_tuple_iter)) # 2 # 【5】集合类型 num_set = {1, 2, 3} num_set_iter = iter(num_set) print(num_set_iter) # print(num_set_iter.__next__()) # 1 print(next(num_set_iter)) # 2
【3】总结
# 具有 __iter__() 和 __next__() 的对象就是迭代器对象 # 在八大基本数据类型中 # 除了 整数、浮点数、布尔 # 其他的都是迭代器对象 # 迭代器对象一定是可迭代对象 # 可迭代对象是 具有 __iter__() 的对象 ---> 生成一个可迭代对象 # 迭代器对象是 具有 __iter__() 和 __next__() 的对象 --> 调用上面可迭代对象的 next 方法
【四】迭代器的优缺点
【1】优点
为序列和非序列类型提供了一种统一的迭代取值方式
不使用索引进行取值
取到值的时候会保存到当前的状态,下一次从这个位置开始向下取值
【2】缺点
除非取尽,否则无法获取迭代器的长度
只能取下一个值,不能回到开始,更像是’一次性‘的,迭代器产生后的唯一目标就是重复执行next方法直到值取尽,否则就会停留在某个位置,等待下一次调用next;
若是要再次迭代同个对象,你只能重新调用iter方法去创建一个新的迭代器对象,如果有两个或者多个循环使用同一个迭代器,必然只会有一个循环能取到值。
【五】什么是生成器
通过生成器,可以逐个生成序列中的元素,而无需一次性生成整个序列
生成器在处理大数据集时,具有节省内存、提高效率的特点。
# 假设一个数据库里 表里面存了1亿条数据 # 读数据时---> 使用 read() 内存会直接爆满导致电脑卡死 # 使用生成器--->一次取100行进行处理 ---->再取100行进行处理,以此类推
【六】生成器的创建方式
【1】列表推导式
使用列表推导式时,可以将列表推导式的方括号改为圆括号,即可创建一个生成器。
# 列表生成式生成列表 start_list = [x * 2 for x in range(5)] print(start_list) # [0, 2, 4, 6, 8] # 将列表改成元祖,看起来像元祖推导式,其实是一个生成器对象 G = (x * 2 for x in range(5)) print(G) #at 0x000001873491CC80> # 生成器对象可以强转成列表 print(list(G)) # [0, 2, 4, 6, 8]
【2】yield关键字
使用yield关键字定义一个生成器函数时,生成器函数中的yield语句会暂停函数执行并返回一个值,下一次调用该函数时会继续执行并返回下一个值。
def my_generator(): yield 1 yield 2 yield 3 g = my_generator() print(next(g)) # 输出:1 print(next(g)) # 输出:2 print(next(g)) # 输出:3
【七】生成器案例
def eater(): print('开始吃饭 ovo ') while True: food = yield print(f'得到的食物是 :>>>> {food}, 开始吃饭喽 :>>>> {food}')
【1】调用函数
res = eater() print(res) #print(res.__next__()) # 打印开始吃饭 # None 原因就是在生成器内部的 yield 中没有返回值 print(res.__next__()) # 打印 得到的食物是 :>>>> None, 开始吃饭喽 :>>>> None # None 原因就是在生成器内部的走完了上面的 又回到了 yield 中结果 yield 没有返回值
【2】向生成器中传值
res = eater() print(res) #print(res.__next__()) res.send("鱼香肉丝") #得到的食物是 :>>>> 鱼香肉丝, 开始吃饭喽 :>>>> 鱼香肉丝 # 想yield 传值并且让生成器向下走一下 print(res.__next__()) #得到的食物是 :>>>> None, 开始吃饭喽 :>>>> None print(res.send("宫保鸡丁")) #得到的食物是 :>>>> 宫保鸡丁, 开始吃饭喽 :>>>> 宫保鸡丁 #None
【八】装饰器 + 生成器
def init_iter(func): # func 我的生成器函数 def inner(*args, **kwargs): # g 得到的生成器对象 g = func(*args, **kwargs) # 调用自己生成器向下走 next(g) # 走回来的返回值返回出去 return g return inner @init_iter def eater(): print('开始吃饭 ovo ') while True: food = yield print(f'得到的食物是 :>>>> {food}, 开始吃饭喽 :>>>> {food}') res = eater() res.send("鱼香肉丝") res.send("宫保鸡丁")
【九】生成器内部修改可变数据类型
def init_iter(func): # func 我的生成器函数 def inner(*args, **kwargs): # g 得到的生成器对象 g = func(*args, **kwargs) # 调用自己生成器向下走 next(g) # 走回来的返回值返回出去 return g return inner @init_iter def eater(): print('开始吃饭 ovo ') food_list = [] while True: food = yield food_list.append(food) print(f'得到的食物是 :>>>> {food}, 开始吃饭喽 :>>>> {food}') print(f'当前后厨已经做好了 :>>>> {food_list}') res = eater() res.send("鱼香肉丝") res.send("宫保鸡丁") # 输出结果: 开始吃饭 ovo 得到的食物是 :>>>> 鱼香肉丝, 开始吃饭喽 :>>>> 鱼香肉丝 当前后厨已经做好了 :>>>> ['鱼香肉丝'] 得到的食物是 :>>>> 宫保鸡丁, 开始吃饭喽 :>>>> 宫保鸡丁 当前后厨已经做好了 :>>>> ['鱼香肉丝', '宫保鸡丁']
【十】yield + next搭配着使用
def my_range(start, stop, step): ''' :param start: 0 :param stop: 5 :param step: 1 ''' print("start") while start < stop: yield start start += step print("end") res = my_range(0, 5, 1) print(res) #print(res.__next__()) # 0 print(res.__next__()) # 1 print(res.__next__()) # 2 print(res.__next__()) # 3 print(res.__next__()) # 4 # 这里会报错 ---》 把我掏空了 --- 没有可迭代的值可以被获取了 print(res.__next__()) # StopIteration
def init_iter(func): def inner(*args, **kwargs): try: generator = func(*args, **kwargs) next(generator) return generator except StopIteration: pass return inner def range_(start, stop, step): while start < stop: yield start start += step # for 循环内部做了异常捕获 for i in range_(0,5,1): print(i) def my_range(start, stop, step): def range_(start, stop, step): while start < stop: yield start start += step res = range_(start, stop, step) while True: try: print(res.__next__()) except StopIteration: break res = my_range(start=1, stop=5, step=1) res #输出结果 0 1 2 3 4 1 2 3 4
链接:https://www.cnblogs.com/chosen-yn/p/18143555
-
字符串
+关注
关注
1文章
585浏览量
20563 -
Next
+关注
关注
0文章
6浏览量
5997 -
迭代器
+关注
关注
0文章
44浏览量
4329
原文标题:【十】yield + next搭配着使用
文章出处:【微信号:magedu-Linux,微信公众号:马哥Linux运维】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
评论