迭代器&生成器

一、迭代器

拥有__iter_方法和__next__方法的对象就是迭代器
1、迭代
迭代是访问集合元素的一种方式,可以将某个数据集内的数据’一个挨着一个取出来’就叫做迭代
2、可迭代协议
协议就是互相规定好的,可迭代协议的定义非常简单,就是内部实现__iter__。
方法。
3、协议迭代器
必须拥有__iter__方法和__next__方法。
4、能被for 循环的内容
list、dic、str、set、tuple、range()、enumerate、f.open()

for i in 123:#报错整数不可迭代的
#     pass

5、dir()方法获取对相应数据类型的所有方法。
dir()获取对应数据类型的所有方法,带有下划线的方法叫做双下方法,例如print(dir([]))
6、查看[],{},’’,range()共有的方法
使用集合的交集进行获取找到__iter__方法。有此方法的对象就是一个可以被迭代的对象

ret=set(dir([]))&set(dir({}))&set(dir(''))&set(dir(range(2)))
print(ret)
print('__iter__'in dir(int))#False int中的数据类型方法没有__iter__
print('__iter__'in dir(bool))#False 同上

7、__iter__方法的作用是返回一个迭代器。
一个列表执行了__iter__()方法后返回值就是一个迭代器

print([].__iter__())#<list_iterator object at 0x00000000007400F0>

8、打印一下迭代器中的方法

t=set(dir([].__iter__()))-set(dir([]))
print(t)
#{'__next__', '__length_hint__', '__setstate__'}

setstate:决定取值的位置
length_hint :获取元素的个数
next:获取元素

9、for 循环原理
1、for循环一个可迭代的对象(实现__iter__方法)
2、__iter__方法返回一个迭代器(迭代器实现了__iter__方法和__next__方法)
3、先判断对象地方可迭代,然后调用迭代器的__next__方法获取值

10、利用迭代器求斐波那契数列

class Fibonacci(object):

    def __init__(self, all_num):
        self.all_num = all_num
        self.a = 1
        self.b = 1
        self.current_num = 0

    def __iter__(self):
        return self  # 返回自己 调用 自己的__next__()方法

    def __next__(self):
        if self.all_num <= 2:
            self.current_num += 1  # 1,2,3
            if self.current_num == 3:
                raise StopIteration
            return self.a
        else:
            if self.current_num < self.all_num:
                ret = self.a  # 1
                self.a, self.b = self.b, self.a + self.b
                # a=1, b=2
                # a=2, b=3
                self.current_num += 1
                return ret
            else:
                raise StopIteration

for i in Fibonacci(10):
    print(i)

11、迭代器作用和应用场景
1、节约内存,取得时候在生成数据,
2、数据类型转换 例如list和元组之间的转换底层就是使用的迭代器
**

二、生成器

**
生成器的本质就是迭代器;生成器包括两种:生成器函数和生成器表达式

1、生成器函数
一个包含yield关键字的函数就是一个生成器函数。并且yield不能和return共用,并且yield
只能用在函数内。
1)生成器函数执行后会得到一个生成器作为返回值,并且不会执行函数体。
2)执行了__next__()方法之后才会执行函数体,并且获得返回值。
3)next()内置方法,内部调用生成器函数的__next__()方法。
4)yield和return相同的是可以返回值,但是不同的是yield不会结束函数

练习1、创建一个生成器并且调用

def generator():
       print('zzz')
       yield
ret=generator()
print(ret)#返回一个生成器对象,并没有执行生成器中的函数体
ret.__next__()#调用__next__()方法执行生成器

练习2:创建一个生成器,并且设置返回值

def generator():
      print('zzzz')
      yidld 1#添加返回值

ret=generator()
res=ret.__next__()
print(res)

练习3:创建生成器,定义多个yield值

def generator():
print('zzzz')
yield 1
print('xxxx')
yield 2

ret=generator():
res=ret.__next__()
print('--------->>>',res)
res=ret.__next__()
print('--------->>>',res)

练习4:创建生成器,生成200万桶康师傅方便面。

def ksf():
for i in range(2000000):
yield'康师傅方便面%s' % i

generator=ksf()
for i in generator:
     print(i)

2、send()
send() 获取下一个值的效果和next()基本一致,只是在获取下一个值的时候,给上一个yield的位置传递一个数据
使用send的注意事项
1)第一次使用生成器的时候 ,是用next获取下一个值
2)最后一个yield不能接受外部的值

练习1:使用send()方法给yield传递参数

def generator():
      peint('a')
      count=yield 1
      print('------>',count)
      print('b')
      yield 2
g=generator()
next(g)
ret2=g.send('123')
print(ret2)

练习2:计算移动平均值

def fun_avg():
count=1
get_num=0
acg=0
total=0
while True:
get_num=yield avg
total=total+get_num
avg=total/count
count+=1


g=fun_avg()
next(g)
print(g.send(10))#打印10
print(g.send(20))#打印15
print(g.send(30))#打印20

3、yield form
刚知道了yield,那么yield from又是什么呢? 它是循环遍历容器类型
现在做一个练习,用for循环取出g1生成器中所有的值。

def gen1()
     for c in 'ab':
         yield c
     for i in range(3):
         yield i

g=gen1()
for i in g:#用for循环遍历出gen1()中的值
     print(i)
print(list(gen1()))#直接将遍历出来的值赋值到列表中   

现在我们再用yield from 遍历出可变数据类型中的数据

def gen2():
      yield from 'ab'
      yield from range(3)
g=gen2()
for i in g:
     print(i) 
print(list(gen2()))    

4、生成器表达式
生成器表达式,跟列表推导式差不多
格式:将列表解析式[]改成()即可。
我们来用生成器表达式进行数数,如下:

g=(i for i in range(10))
print(g)
for j in g:
     print(j)

我们再来模拟鸡下蛋再进行一个练习:
首先使用列表推导式生成

egg_list=['鸡蛋{}'.format(i)for i in range(10)]
print(egg_list)#你会发现列表会一下堆满了‘鸡蛋’

使用生成器表达式再来一次

egg_list=('鸡蛋{}'.format(i)for i in range(10))
print(egg_list)
print(next(egg_list))#调用一次next打印一个1个‘’鸡蛋‘’
print(egg_list.__next__())
print(next(egg_list))
print(egg_list)
print(list(egg_list))
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值