迭代器、生成器

print(dir([])) #显示列表拥有的所有方法

1 print(dir([])) #显示列表拥有的所有方法
2 
3 
4 
5 #结果如下:
6 ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
View Code
可以被for循环的都是可迭代的,要想可迭代,内部必须有一个__iter__方法
iterable  可迭代的  —> _iter_  只要含有_iter_方法的都是可迭代的
[]._iter_() 迭代器     —>_next_ 通过next就可以从迭代器中一个一个的数值
 
__iter__方法做了什么事情呢?
l = [1,2,3,4,5]
print(l.__iter__())


#结果
<list_iterator object at 0x109896518>

执行了list([1,2])的__iter__方法,得到了一个list_iterator,现在又得到了一个新名词——iterator

iterator,这里给我们标出来了,是一个计算机中的专属名词,叫做迭代器。

'''
dir([1,2].__iter__())是列表迭代器中实现的所有方法,dir([1,2])是列表中实现的所有方法,都是以列表的形式返回给我们的,为了看的更清楚,我们分别把他们转换成集合,
然后取差集。
'''
#print(dir([1,2].__iter__()))
#print(dir([1,2]))
print(set(dir([1,2].__iter__()))-set(dir([1,2])))

结果:
{'__length_hint__', '__next__', '__setstate__'}

我们看到在列表迭代器中多了三个方法,那么这三个方法都分别什么用途呢?

iter_l = [1,2,3,4,5,6].__iter__()
#获取迭代器中元素的长度
print(iter_l.__length_hint__())
#根据索引值指定从哪里开始迭代
print('*',iter_l.__setstate__(4))
#一个一个的取值
print('**',iter_l.__next__())
print('***',iter_l.__next__())

__next__能让我们一个一个取值

在for循环中,就是在内部调用了__next__方法才能取到一个一个的值。

那接下来我们就用迭代器的next方法来写一个不依赖for的遍历。

l = [1,2,3,4]
l_iter = l.__iter__()
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)

但是这段代码在最后报错了,因为我们一直取next取到迭代器里已经没有元素了,就会抛出一个异常StopIteration,告诉我们,列表中已经没有有效的元素了。

接下来稍作修改,把这个异常报错处理掉:

l = [1,2,3,4]
l_iter = l.__iter__()
while True:
    try:
        item = l_iter.__next__()
        print(item)
    except StopIteration:
        break

现在我们就使用while循环实现了原本for循环做的事情,我们是从l_iter获取一个一个的值,这个l_iter就是一个迭代器。

只要含有_iter_方法的都是可迭代的   ----可迭代协议
迭代器协议 ——内部含有_next_和_iter_方法的就是迭代器
迭代器的好处:
                        从容器类型中一个一个的取值,会把所有的值都取到。
                        节省内存空间
                        迭代器并不会在内存中再占用一大块内存,而是随着循环每次生成一个,
                        每次_next_提供一个
 
 
 
生成器:
    生成器函数

Python中提供的生成器:

1.生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次重它离开的地方继续执行

2.生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表

 

生成器Generator:

  本质:迭代器(所以自带了__iter__方法和__next__方法,不需要我们去实现)

  特点:惰性运算,开发者自定义

生成器函数

 一个包含yield关键字的函数就是一个生成器函数。yield可以为我们从函数中返回值,但是yield又不同于return,return的执行意味着程序的结束,调用生成器函数不会得到返回的具体的值,而是得到一个可迭代的对象。每一次获取这个可迭代对象的值,就能推动函数的执行,获取新的返回值。直到函数执行结束。

def count():
    yield 1
    yield 2
    yield 3
    yield 4
    yield 5
    yield 6
    yield 7
    yield 8

g = count()
print(g)
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())



#结果:
<generator object count at 0x10c30ebf8>
1
2
3
4
5
6
7
8

生成器的应用实例:

def tail(filename):
    f = open(filename,encoding = 'utf-8')
    while True:
        line = f.readline()
        if line.strip():
            yield line.strip()
            
g = tail('file')
for i in g:
    if 'python' in i:
        print('***',i)
监听用户输入内容并过滤出有关python关键字的行

 

生成器函数进阶:

def generator():
    print(123)
    content = yield 1
    print('######',content)
    print(456)
    yield 2
 
 
g = generator()
ret = g.__next__()
print('****',ret)
ret = g.send('hello’)   #send的效果和next一样
print('***',ret)
 
#结果:
123
**** 1
###### hello
456
*** 2
 
#send 获取下一个值的效果和next基本一致
#只是在获取下一个值的时候,给上一个值的位置传递一个数据
        #使用注意事项:
                    #第一次使用生成器的时候,必须用next获取下一个值
                    #最后一个yield不能接受外部的值
 
实例:获取移动平均值
 
def average():
    sum = 0
    count = 0
    avg = 0
    while 1:
        num = yield avg
        sum += num
        count += 1
        avg = sum/count
 
avg_g = average()
avg_g.__next__()
avg1 = avg_g.send(10)
print(avg1)
avg1 = avg_g.send(20)
print(avg1)
avg1 = avg_g.send(30)
print(avg1)
 
结果:
10.0
15.0
20.0
 
 
#列表推导式
list = [i for i in range(10)]
print(list)   #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
#生成器表达式
g = (i for i in range(10))
print(g)      #<generator object <genexpr> at 0x100e97d00>  g是一个生成器
#两者区别:
    #括号不一样
    #返回的值不一样  === 几乎不占用内存
 
g1 = (i*i for i in range(10))
for i in g1:
    print(i)
#[每一个元素或者是和元素相关的操作  for 元素 in 可迭代数据类型]  #遍历之后挨个处理
#【满足条件的元素相关的操作 for 元素 in 可迭代数据类型  if 元素相关的条件】 #筛选功能
 
#30以内所有能被3整出的数
 
ret = [i for i in range(30) if i%3 == 0]
print(ret)

 

转载于:https://www.cnblogs.com/shi-guang/p/8178787.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值