迭代器和生成器
1.iterable 可迭代:
可迭代的数据类型:列表、字符串、集合、字典 、元祖
- 迭代器我们可以理解为一个容器。我们从这个容器中一个接一个把值取出来,这个过程就是迭代过程
-
'__iter__' 内部含有'__iter__'方法的数据类型就是可迭代的
2.iterator迭代器:
迭代器我们可以理解为一个容器。我们从这个容器中一个接一个把值取出来,这个过程就是迭代过程
迭代器的用法
- Python中一切皆对象,可迭代的等于可迭代对象
- 可迭代的 必须含有'__iter__' 的方法 #可迭代协议
- 迭代器比可迭代多一个'__next__'方法
- 迭代器:包含'__next__'和'__iter__'的方法就是迭代器 #这个是迭代器协议
- 包含'__next__'的可迭代对象就是迭代器。
- 迭代器是可迭代的 的一部分
迭代器的调用
- for循环是让我们更简单的使用迭代器
- 用迭代器取值就不需要关心索引或者key的问题了
- 迭代器是个好东西
- 目前我们已知的可迭代的都是python提供给我们的
- range()
- f
- enumerate()
- 但是在平时我们写代码的过程中我们用for循环就足够了
如何判断一个变量是迭代器 或者 是可迭代的
l = [1,2,3,4] l_iter = l.__iter__() print('__iter__' in dir(l)) print('__next__' in dir(l_iter)) # 运行结果: True True
isinstance() 函数来判断一个对象是否是一个已知的类型,类似 type()。
#引入可迭代 from collections.abc import Iterable print(isinstance([1,2,3,4],Iterable)) #引入迭代器 from collections.abc import Iterator print(isinstance([1,2,3,4],Iterator)) #运行结果: True False
3.生成器
生成器是一次生成一个值的特殊类型函数。可以将其视为可恢复函数。# 调用该函数将返回一个可用于生成连续 x 值的生成【Generator】,简单的说就是在函数的执行过程中,yield语句会把你需要的值返回给调用生成器的地方,然后退出函数,下一次调用生成器函数的时候又从上次中断的地方开始执行,而生成器内的所有变量参数都会被保存下来供下一次使用。
自己写的可迭代的就是生成器 生成器的本质是可迭代的生成器所以优点跟迭代器一样 不同点:生成器是自己写Python代码
生成器的实现是由两种方式:
第一种:生成器函数
#generator 生成器 迭代器的一种 def g_func(): print('qwer') yield 1 yield 2 #返回 但没终止 g = g_func() print(g) print(g.__next__()) print(g.__next__())
#生成器函数与普通函数区别:
#1.生成器函数中含有yield关键字
#2.生成器函数调用的时候不会立即执行,而是返回一个生成器
#第二种:生成器表达式
def gen(): for i in range(4): yield i base = gen() for n in (2,10): base = (i+n for i in base) print(list(base)) [21,22,23,24] #简单解答: 因为for循环了两次,并对base从新赋值了,所以可以简化为(i+n for i in (i+n for i in base)) 而n 全部引用了后赋值的10。最里面的base引用的是gen。
列表推导式:
x = [i**2 for i in y] print(x)
[1, 4, 9, 16, 25, 36, 49, 64]
求偶及取余:
# l = [声明量 遍历范围 条件判断 ] l = [i for i in range(10) if i % 2 == 0 ] print(l) [0, 2, 4, 6, 8]
#区分大小写
mcase = {'a': 10, 'b': 34, 'A': 7, 'Z': 3} mcase_frequency = {k.lower(): mcase.get(k.lower(), 0) + mcase.get(k.upper(), 0) for k in mcase} print(mcase_frequency)
# 字典推导式
dic = {'a':10,'b':20} dic_t = {dic[k]:k for k in dic} print(dic_t)
- 生成器函数 是生成一个生成器的函数 生成器的本质是迭代器
- 特点:带有yeild关键字,调用后函数内代码不执行
- 触发的方式:next 、 send 、 for循环
- next 和 send 执行几次 拿几次数据 取完报错
- for循环每次取一个 去玩为止 不会报错
- send(空)相当于 next
- send是在next的基础上传一个值到生成器函数内
- send不能用在生成器操作的第一次
def average(): total = 0.0 count = 0 average = None while True: term = yield average total += term count += 1 average = total/count g_avg = average() print(g_avg.__next__()) print(g_avg.send(10)) print(g_avg.send(20))