迭代器生成器

迭代器

迭代器是访问集合元素的一种方式。

迭代器保存的是生成数据的代码,并不是代码生成的数据结果。

迭代器实现了循环,减少内存空间的使用,可以规定数据的生成方式。


1.到底什么是迭代器,判断是否是一个迭代器,跟着栗子来....

for temp in temp_obj:

     pass

判断步骤:

  1. 判断 temp_obj 对象是否可以迭代。(可迭代对象移动包含__iter__方法)
  2. 在第一步条件成立的情况下,调用其__iter__方法,会得到__iter__方法 return 的返回值。(可迭代的对象
  3. __iter__方法返回的是一个迭代器

2.在开发过程当中,创建对象后添加很多数据,能否通过for取出这些数据

  1. 创建的这个对象的类里边必须包含一个__iter__方法。
  2. Iter方法必须返回一个迭代器的对象。
  3. 迭代器:必须包含__iter__方法和__next__方法。一大特点可以取里边的值。next工作原理就是通过重复调用next()方法,直到捕获一个异常。

3.使用迭代器和不使用迭代器的区别:

当你需要一些数据的时候可以这样做:

  1. 可以找列表将数据预先存起来。占用空间大
  2. 什么时候用什么时候生成。只存储生成方式。占用空间小。

4.并不是只有for循环能接受可迭代对象,可以通过列表或元组去取值:

A=[11,22,33,44,55]
li=list(fibIterator(A))
Print(li)
#先生成一个空列表,再去调用list里的迭代器,
#因为A是一个迭代对象,通过iter函数就会找到迭代器,通过next去取值。
li=tuple(fibIterator(A))
Print(li)

5.判断其是否是一个可迭代的对象

from collections.abc import Iterable
from collections.abc import Iterator
import time
# print(isinstance([11,22,33],Iterable))
# print(isinstance("1111",Iterable))
# print(isinstance(111,Iterable))

迭代器案例:

class Fibonacci(object):
    def __init__(self,number):
        self.number=number
        self.count=0
        self.a=0
        self.b=1
    def __iter__(self):
        return self
    def __next__(self):
        if self.count<self.number:
            ret=self.a
            self.a,self.b=self.b,self.a+self.b
            self.count+=1
            return ret
        else:
            raise StopIteration
feibo=Fibonacci(10)
for i in feibo:
    print(i)

这里说一下跳出迭代器next()方法,可以抛出StopIteration异常就无法继续返回下一个值了,否则最后会一直调用返回None。

生成器

生成器是一种特殊的迭代器。在 Python 中,使用了 yield 的函数被称为生成器(generator)。

1.创建生成器的两种方式:

  • 将列表推导式的中括号换为圆括号(

    列表推导式:存储数据占用内存大

  • yield创建生成器 (生成器:只存放数据的存储方式,占用内存小)

2.启动生成器的方式:除了next,还有send。

def createnum(all_num):
    print("-----1-----")
    a,b=0,1
    num=0
    while num<all_num:
        # print(a)
        print("-----2-------")
        yield a#yield会将函数暂停,下次从下一个再次执行。
        #运行到yield时会把yield后a传递给number
        #在下次for循环会直接从yield处开始执行,并不会从头开始执行。
        print("-----3-----")
        a,b=b,a+b
        num+=1
        print("------4-------")
#如果在调用createnum()的时候,如果有yield,就不是调用函数,就是创建了一个
#生成器对象。
obj=createnum(10)
#生成器是一种特殊的迭代器。
# for number in obj:
#     #直到没有for循环-->结束。
#     print(number)
while True:
    try:
        ret=next(object)
        print(ret)
    except Exception as ret:
        break

send方式:

可以传参数,send传送的是yield a表达式的最后的结果
在生成器在生成数的时候,send可用于传送新的参考值,接收可以yield前加参数接收。
send不要放到next前。启动第一次一般用next.

def createnum(all_num):
    a,b=0,1
    num=0
    while num<all_num:
        ret=yield a
        print(">>>>ret", ret)
        a,b=b,a+b
        num+=1
obj=createnum(10)
ret=next(obj)#不能传参数
print(ret)
ret=obj.send('xxxxxx')
print(ret)

3.使用yield完成多任务(并发)

进程之间切换多任务,占用资源会很大。而且创建进程(从硬盘上加载代码、申请内存空间)、释放进程是个很复杂的过程,浪费大量的时间。

进程没有线程效率高,但协程比线程运行效率更高。协程调用一个任务就像调用一个函数这样简单,切换耗费的资源最少。进程消耗资源最多,线程次之。

参考代码:

import time
def task_1():
    while True:
        print("-----1-----")
        time.sleep(1)
        yield


def task_2():
    while True:
        print("-----2-----")
        time.sleep(1)
        yield

#两个函数一起执行
if __name__ == '__main__':
    t1=task_1()
    t2=task_2()
    while True:
        next(t1)
        next(t2)

只需要在要执行的函数加yield即可

3.1使用greenlet来实现多任务

pip3 install greenlet

参考代码:

from greenlet import greenlet
import time

def test1():
    while True:
        print("----A----")
        gr2.switch()
        time.sleep(0.5)

def test2():
    while True:
        print("----B----")
        gr1.switch()
        time.sleep(0.5)


gr1=greenlet(test1)#返回greelet对象
gr2=greenlet(test2)

#切换到gr1中运行
gr1.switch() #greenlet的switch方法可以实现函数的切换

3.2 gevent的网络异步并发库

pip install gevent

用多协程实现多任务的方式是:单线程利用了等待耗时的时间去执行其他事情。线程结束,协程也就结束了

import gevent

def f1(n):
    for i in range(n):
        print(gevent.getcurrent(),i)
        gevent.sleep(0.5)

def f2(n):
    for i in range(n):
        print(gevent.getcurrent(),i)
        gevent.sleep(0.5)

def f3(n):
    for i in range(n):
        print(gevent.getcurrent(),i)
        gevent.sleep(0.5)

#第一个参数为指定任务去去哪执行
#第二个传递的所需参数,有写无不写
print("------1------")
g1=gevent.spawn(f1,5)#创建greenlet对象
print("------2------")
g2=gevent.spawn(f2,5)
print("------3------")
g3=gevent.spawn(f3,5)
print("------4------")
g1.join()#等待g1执行完
g2.join()
g3.join()

这里的延时和堵塞需要都要换成gevent里面的方法。有简单的方法实现:给程序打补丁,使用

import gevent
from  gevent import monkey
monkey.patch_all()

使用

monkey.patch_all()代码不用改,会自动改成gevent代码。

monkey将当前整个代码,读到某个地方去,然后将当前代码的所有耗时操作检查一遍,全有换成gevent中的方法,这样就可以按照你的方法写代码。

import gevent
import time
from  gevent import monkey
monkey.patch_all()
def f1(n):
    for i in range(n):
        print(gevent.getcurrent(),i)
        time.sleep(0.5)

def f2(n):
    for i in range(n):
        print(gevent.getcurrent(),i)
        time.sleep(0.5)

def f3(n):
    for i in range(n):
        print(gevent.getcurrent(),i)
        time.sleep(0.5)

#第一个参数为指定任务去去哪执行
#第二个传递的所需参数,有写无不写
print("------1------")
g1=gevent.spawn(f1,5)#创建greenlet对象
print("------2------")
g2=gevent.spawn(f2,5)
print("------3------")
g3=gevent.spawn(f3,5)
print("------4------")
gevent.joinall([
    gevent.spawn(f1,5),
    gevent.spawn(f2,5),
    gevent.spawn(f3,5)
])

这里可以用joinall()方法中放列表来实现等前一个执行完再执行自己。如果分开写:

g1.join()#等待g1执行完
g2.join()
g3.join()

如果数量太大,写出来太麻烦

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看REAdMe.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看REAdMe.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看READme.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值