函数进阶-迭代器
双下方法:
很少直接调用,一般情况下,都是通过其他语法触发的(Python解释器调用的方法)
可迭代协议 与 迭代器协议
可迭代的iterable与迭代器iter
可迭代协议:含有__iter__方法的都是可迭代的。
可迭代的,一定可以被for循环。只要含有__iter__()方法能被for循环。
迭代器协议:含有__iter__方法和__next__方法的。
迭代器一定可迭代。
可迭代的通过iter()方法就能得到一个迭代器。
迭代器的特点:
1.惰性计算:迭代器只在需要时生成数据,适合处理大数据集,减少内存占用。
2.随着循环每次在内存中生成一个值,而不是全部。每次调用next时返回一个值,也不是全部。
list1 = [1, 2, 3] # 只有__iter__方法,没有__next__方法,说明列表是可迭代的 print('__iter__' in list1.__dir__()) print('__next__' in list1.__dir__()) # 输出结果 # True # False # 通过iter()方法将列表转换为迭代器。并验证是否存在__iter__方法与__next__方法。 list1_iterator = iter(list1) # 调用iter方法返回当前可迭代对象的迭代器 print('__iter__' in list1_iterator.__dir__()) print('__next__' in list1_iterator.__dir__()) # 输出结果: # True # True # 一个类中只要有iter方法就会认为是可迭代的,如果既有iter方法还有next方法,就会认为是迭代器 from collections import Iterator from collections import Iterable class A: def __iter__(self): pass def __next__(self): pass a = A() print(isinstance(a, Iterator)) # 判断是否是迭代器 print(isinstance(a, Iterable)) # 判断是否是可迭代的 # 输出结果: # True # True # 迭代器中的__next__()方法 # __next__():以0为起点,获取迭代器中的下一个值 print(list1_iterator.__next__()) # list1_iterator中的第一个值 print(list1_iterator.__next__()) # list1_iterator中的第二个值 # 输出结果 # 1 # 2 # 迭代器中的__iter__()方法 iterator = list1.__iter__() # 返回一个当前可迭代对象的迭代器 print(iterator) # 输出结果: # <list_iterator object at 0x00000271EBB2B970> # 迭代器能节省内存的演示 print(range(1, 100000000000)) # 很快生成。因为range是一个迭代器,一个一个的返值 print(list(range(1, 100000000000))) # 会报错MemoryError,电脑内存不够容纳这么大的列表。因为list不是迭代器,会一次生成全部数据。
函数进阶-生成器
生成器的本质,就是自己写的迭代器。一次返回一个值,而不是一次性生成所有的值。生成器通过使用 yield
关键字定义。(有yield的函数就是生成器函数)
生成器的两种形式:1.生成器函数。2,生成器表达式
生成器函数
生成器函数的定义:含有yield关键字的函数就是生成器函数;
生成器函数的特点:
1.调用函数时不会执行函数内部代码,而是返回一个生成器内存地址。
2.每次调用next()方法的时候会取到一个值。
3.直到取完最后一个,再执行next时会报错。
yield关键词
yield与return不能共用。与 return
不同,yield
不会终止函数的执行,而是暂停函数的执行,并返回一个值给调用者。函数在下次调用时会从上次暂停的地方继续执行。
def simple_generator(): yield 1 yield 2 yield 3 gen = simple_generator() print(next(gen)) # 输出: 1 print(next(gen)) # 输出: 2 print(next(gen)) # 输出: 3 # print(next(gen)) # 抛出 StopIteration 异常
生成器函数代码演示:
def generator(): print('生成器函数中打印的数据1') yield 1 print('生成器函数中打印的数据2') yield 2 print('生成器函数中打印的数据3') yield 3 g = generator() # 返回一个生成器 print(g) # 结果:<generator object generator at 0x103141540> print(g.__next__()) # 通过next取值
生成器函数取值的三种方式:
1.通过__next__()取值:上面的演示代码中已经演示
2.通过for循环取值:
def generator(): print('生成器函数中打印的数据1') yield 1 print('生成器函数中打印的数据2') yield 2 print('生成器函数中打印的数据3') yield 3 g = generator() # 返回一个生成器 for i in g: print(i) 执行结果: 生成器函数中打印的数据1 1 生成器函数中打印的数据2 2 生成器函数中打印的数据3 3
3.通过数据类型转换从生成器中取值(比较占用内存):
def generator(): print('生成器函数中打印的数据1') yield 1 print('生成器函数中打印的数据2') yield 2 print('生成器函数中打印的数据3') yield 3 g = generator() print(list(g)) # 执行结果: 生成器函数中打印的数据1 生成器函数中打印的数据2 生成器函数中打印的数据3 [1, 2, 3]
生成器函数与普通函数的区别:
1. 定义方式
- 普通函数:使用
return
关键字返回一个值,函数执行完毕后结束。 - 生成器函数:使用
yield
关键字逐个返回值,函数执行可暂停并保持状态。
2. 返回值
- 普通函数:返回单一值,并终止函数执行。
- 生成器函数:返回一个生成器对象,可以多次调用,逐个生成多个值。
3. 内存管理
- 普通函数:一次性生成所有返回值,可能导致高内存占用。
- 生成器函数:按需生成值,内存占用小,适合处理大数据。
4. 调用方式
- 普通函数:调用后不可再用,必须重新调用。
- 生成器函数:可以通过
next()
逐步获取值,也可以在for
循环中迭代。
5. 状态保持
- 普通函数:无法保持执行状态,调用后状态丢失。
- 生成器函数:保持状态,每次调用继续上次暂停的位置。
总结
- 生成器函数通过
yield
提供了惰性求值的能力,适合需要高效内存管理和逐步生成数据的场景。
生成器表达式
标签:__,函数,迭代,Python,18,生成器,next,print From: https://www.cnblogs.com/mingbo-1/p/18474262