Python3.x---第五篇

迭代器与生成器

  • 迭代器


'''
什么是可迭代对象
1.可迭代对象用来:for in 循环
2. list,dict,tuple,str,set
3.需要满足:__iter__的方法,并且这个方法要返回一个迭代器对象

什么是迭代器
1.用来返回数据,每次循环都会调用迭代器的__next__或者next方法,通过这个方法来获取数据
2.需要满足条件:在Python2中:需要实现__iter__,next
                在Python3中,需要实现__iter__和__next__方法

iter函数:
用来获取一个可迭代对象的迭代器
'''

from collections.abc import Iterable,Iterator

# ret = [1,2,3]
# ret1 = (1,2,3)
# ret2 = 'abc'
# ret3 = 123
#
# print(isinstance(ret,Iterable))
# print(isinstance(ret1,Iterable))
# print(isinstance(ret2,Iterable))
# print(isinstance(ret3,Iterable))

# #判断一个对象是否是一个可迭代对象
# class MyRange(object):
#     def __iter__(self):
#         pass
#
# ret4 = MyRange()
# print(isinstance(ret4,Iterable))

# #判断一个对象是否是迭代器对象
# class MyRange(object):
#     def __iter__(self):
#         pass
#
#     def __next__(self):
#         pass
#
# ret = MyRange()
# print(isinstance(ret,Iterator))

#自定义一个迭代器
#类似于list或者类似于range的对象
#range(1,10)
class MyRangeIterator(object):
    def __init__(self,start,end):
        self.index = start
        self.end = end

    def __iter__(self):
        return self

    def __next__(self):
        if self.index < self.end:
            temp = self.index
            self.index += 1
            return temp
        else:
            raise StopIteration()

class MyRange(object):
    '''
    MyRange是可迭代对象
    '''
    def __init__(self,start,end):
        self.start = start
        self.end = end

    def __iter__(self):
        #这个方法中要返回一个迭代器对像
        return MyRangeIterator(self.start,self.end)

ret = MyRange(1,10)
for x in ret:
    print(x)

print('='*30)
for y in ret:
    print(y)
#for ... in ... 的原理
# ret_iterator = iter(ret)
# while True:
#     try:
#         x = ret_iterator.__next__()
#         print(x)
#     except StopIteration:
#         break

#
# class MyRange(object):
#     '''
#     MyRange是可迭代对象
#     '''
#     def __init__(self,start,end):
#         self.start = start
#         self.end = end
#         self.index = start
#
#     def __iter__(self):
#         #这个方法中要返回一个迭代器对像
#         return self
#
#     def __next__(self):
#         if self.index < self.end:
#             temp = self.index
#             self.index += 1
#             return temp
#         else:
#             raise StopIteration()
#
# ret = MyRange(1,10)
# for x in ret:
#     print(x)
#
# print('='*30)
# for y in ret:
#     print(y)

'''
如果将迭代器和迭代对象都放在一个对象中,那么只可以迭代一次
'''

  • 生成器
'''
为什么用生成器:节省内存

生成器运行原理:yield会一次返回一个结果,并且会冻结当前函数的状态

解决问题:
1.用Python圆括号的方式
2.使用自定义函数

生成器其实也是迭代器,也是可迭代对象,那么可以通过for循环进行遍历,
并且因为他自身集成了迭代器和可迭代对象两个身份,因此他只能被遍历一次。

'''

# ret = [x for x in range(1,1000000000)]
# for x in ret:
#     print(x)

# ret = (x for x in range(1,100000000))
# print(type(ret))
# for x in ret:
#     print(x)



#生成器解决内存满,自定义生成器
# def my_gen():
#     yield 1
#     yield 2
#     yield 3
#
# ret = my_gen()
# # print(type(ret))
# print(next(ret))
# print(next(ret))
# print(next(ret))
# print(next(ret))
def my_gen(start,end):
    index = start
    while index <= end:
        yield index
        index += 1

#生成器有两个身份,迭代器和可迭代的对象
ret = my_gen(1,10000000)
for x in ret:
    print(x)
# a = 1+2 #右边是表达式
# b = 3
# c = a+b #右边是表达式

def my_gen(start):
    while start < 10:
        #如果是通过next函数执行yield
        #那么yield xxx 永远都是返回None
        temp = yield start
        print(temp)
        start += 1

'''
send方法:
1.也是用来触发代码,直到碰到yield表达式
2.如果用send方法执行刚刚开始的生成器,那么应该传None给send方法。不传或者传其他值都会报错

send与next区别:
1.send方法可以传递值给yield表达式。
2.第一次执行时,send要传None,而next不用。
'''
ret = my_gen(1)
print(ret.send(None))
print(ret.__next__())
#1
print(ret.__next__())
#temp
#2
print(ret.send('zhiliao'))#传递值给yield表达式
#zhiliao
#3
# #生成器中少用return
# def my_gen():
#     print('hello')
#     yield 1
#     return
#     yield 2
#
# ret = my_gen()
# print(next(ret))
# print(next(ret))

#菲波那切数列
# def fib(count):
#     index = 1
#     a,b = 0,1
#     while index <= count:
#         yield b
#         c = b
#         b = a+b
#         a = c
#
#         index += 1
# for x in fib(7):
#     print(x)

def neteasy_musice(duration):
    time = 0
    while time <= duration:
        print('歌曲听到了第%d分钟了' % time)
        time += 1
        yield None

def youku_movie(duration):
    time = 0
    while time <= duration:
        print('电影看到第%d分钟了' % time)
        time += 1
        yield None

if __name__ == '__main__':
    music_iter = neteasy_musice(10)
    movie_iter = youku_movie(20)
    music_stop = False
    movie_stop = False
    while True:
        try:
            next(music_iter)
        except StopIteration:
            print('音乐已经播完')
            music_stop = True

        try:
            next(movie_iter)
        except StopIteration:
            print('电影已经看完')
            movie_stop = True
        if movie_stop and music_stop:
            break
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值