博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
迭代器和生成器
阅读量:5060 次
发布时间:2019-06-12

本文共 4394 字,大约阅读时间需要 14 分钟。

迭代的概念:迭代就是可以被遍历的数据类型,也就是可以被一个一个取出来。

那么可迭代的类型有哪些?

from collections import Iterable                             l = [1,2,3,4]                t = (1,2,3,4)                d = {1:2,3:4}                s = {1,2,3,4}                                             print(isinstance(l,Iterable))print(isinstance(t,Iterable))print(isinstance(d,Iterable))print(isinstance(s,Iterable))
View Code

这里可以看出,元组,列表,字典,集合,包括字符串都是可迭代的。

1)为什么可以被迭代呢?

这就要说一下迭代的协议。

迭代的协议就是内部含有——lter——方法。

2)什么是迭代器?

print([1,2].__iter__())结果
View Code

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

——iterator。

iterator的意思就是迭代器。

迭代器和可迭代的对面之间的区别就是在内容里面多了一个:__next__,这也是他们之间的最根本区别。

__next__:迭代器就是因为多了这个才可以一个个迭代(遍历),

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)
View Code

上路的可迭代对象如果遍历完,那么就会报错。有时候我们就有一些异常的办法把异常处理出去:

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

标准格式就是list.__next__(),这之前要看他是不是可迭代对象,如果不行就用__iter__()把他变成可迭代对象,然后在用next一个个遍历.

迭代器遵循迭代器协议:必须拥有__iter__方法和__next__方法。

3)range()是迭代器吗?

from collections import  Iteratorprint(isinstance(range(100000000),Iterator))  print(isinstance(range(100),Iterator))这里的isinstance是查看里面的值是什么数据类型,Iterator就是看看是不是迭代器。

4)迭代器有什么作用:最重要的一点就是可以节省内存空间。

 

Python中提供的生成器:

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

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

 

生成器Generator:

 

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

 

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

 

 

import timedef genrator_fun1():    a = 1    print('现在定义了a变量')    yield a    b = 2    print('现在又定义了b变量')    yield bg1 = genrator_fun1()print('g1 : ',g1)       #打印g1可以发现g1就是一个生成器print('-'*20)   #我是华丽的分割线print(next(g1))time.sleep(1)   #sleep一秒看清执行过程print(next(g1))初识生成器函数
View Code

 

这里有一些注意:首先运行一次genrator_fun1()的话,只会显示他是一个生成器,不会显示别东西,只有当你调用next(genrator_fun1())的话,他才会运行,但是你掉一次next他就只会运行到第一个yield,就不会再运行,只有你一下子调用2个next的时候,他才会一下子运行2个,并且把值返回到genrator_fun 里,下面谁接收的话,就给谁,另外,每一次调用后,当你重新调用的时候,程序又会重新从第一个开始运行。
ps:如果yield后面带了东西,当你运行到那的时候才会取出来。

 

 

下面是一些例子:

import timadef func():    f=open(filename)    f.seak(0,2)    while True:        line=f.readline()        if not line:            time.sleep(0.2)            continue        else:            yield  linel=func()for line in l:    print(line)
View Code
#初识生成器二def produce():    """生产衣服"""    for i in range(2000000):        yield "生产了第%s件衣服"%iproduct_g = produce()print(product_g.__next__()) #要一件衣服print(product_g.__next__()) #再要一件衣服print(product_g.__next__()) #再要一件衣服num = 0for i in product_g:         #要一批衣服,比如5件    print(i)    num +=1    if num == 5:        break#到这里我们找工厂拿了8件衣服,我一共让我的生产函数(也就是produce生成器函数)生产2000000件衣服。#剩下的还有很多衣服,我们可以一直拿,也可以放着等想拿的时候再拿
View Code
#初识生成器二def produce():    """生产衣服"""    for i in range(2000000):        yield "生产了第%s件衣服"%iproduct_g = produce()print(product_g.__next__()) #要一件衣服print(product_g.__next__()) #再要一件衣服print(product_g.__next__()) #再要一件衣服num = 0for i in product_g:         #要一批衣服,比如5件    print(i)    num +=1    if num == 5:        break#到这里我们找工厂拿了8件衣服,我一共让我的生产函数(也就是produce生成器函数)生产2000000件衣服。#剩下的还有很多衣服,我们可以一直拿,也可以放着等想拿的时候再拿
衣服生产
def averager():    total = 0.0    count = 0    average = None    while True:        term = yield average        total += term        count += 1        average = total/countg_avg = averager()next(g_avg)print(g_avg.send(10))print(g_avg.send(30))print(g_avg.send(5))计算移动平均值(1)
平均值的计算
def init(func):  #在调用被装饰生成器函数的时候首先用next激活生成器    def inner(*args,**kwargs):        g = func(*args,**kwargs)        next(g)        return g    return inner@initdef averager():    total = 0.0    count = 0    average = None    while True:        term = yield average        total += term        count += 1        average = total/countg_avg = averager()# next(g_avg)   在装饰器中执行了next方法print(g_avg.send(10))print(g_avg.send(30))print(g_avg.send(5))
平均值带装饰器

下面是一个生成器yield   from 的一些应用

def gen1():    for c in 'AB':        yield c    for i in range(3):        yield iprint(list(gen1()))def gen2():    yield from 'AB'    yield from range(3)print(list(gen2()))
yield from

 

列表表达式和生成器表达式:

之间的差别:列表表达式占系统内存空间较多,生成器几乎不占内存。

list=[x  for x in range(10000) ]---列表表达式

list=(x  for x in range(10000))---生成器表达式

 

转载于:https://www.cnblogs.com/52forjie/p/7276939.html

你可能感兴趣的文章
IO—》Properties类&序列化流与反序列化流
查看>>
【蓝桥杯】PREV-21 回文数字
查看>>
html 简介
查看>>
python使用上下文对代码片段进行计时,非装饰器
查看>>
js中比较实用的函数用法
查看>>
安装预览版镜像后无法检测到预览版更新的解决方案
查看>>
【bzoj5099】[POI2018]Pionek 双指针法
查看>>
别让安全问题拖慢了 DevOps!
查看>>
JAR打包和运行
查看>>
session如何保存在专门的StateServer服务器中
查看>>
react展示数据
查看>>
测试计划
查看>>
idea设置自定义图片
查看>>
[高级]Android多线程任务优化1:探讨AsyncTask的缺陷
查看>>
选择器
查看>>
rownum 的使用
查看>>
Mysql与Oracle 的对比
查看>>
MVC系列博客之排球计分(三)模型类的实现
查看>>
npm安装
查看>>
阅读笔记02
查看>>