zoukankan      html  css  js  c++  java
  • Python之路——迭代器与生成器

    一、迭代器

      1 # -*- encoding:utf-8 -*-
      2 
      3 
      4 # dir([1,2].__iter__())是列表迭代器中实现的所有方法,dir([1,2])是列表中实现的所有方法
      5 # print(dir([1,2].__iter__()))
      6 # print(dir([1,2]))
      7 # print(set(dir([1,2].__iter__()))-set(dir([1,2])))   # {'__length_hint__', '__setstate__', '__next__'}
      8 
      9 # iter = [1,2,3,4,5,6].__iter__()
     10 # print(iter.__length_hint__())
     11 # print(iter.__next__())
     12 # print(iter.__next__())
     13 # print(iter.__length_hint__())   # 获取迭代器中剩余元素的长度
     14 #
     15 # print('**',iter.__setstate__(0))    # 根据索引值指定从哪里开始迭代
     16 # print(iter.__next__())
     17 # print(iter.__next__())  # 一个一个的取值
     18 # print(iter.__next__())
     19 # print(iter.__next__())
     20 
     21 # l = [1,2,3,5]
     22 # l_iter = l.__iter__()
     23 # item = l_iter.__next__()
     24 # print(item)
     25 # item = l_iter.__next__()
     26 # print(item)
     27 # item = l_iter.__next__()
     28 # print(item)
     29 # item = l_iter.__next__()
     30 # print(item)
     31 # item = l_iter.__next__()    # 如果迭代器里已经没有元素了,会抛出一个StopIteration异常
     32 # print(item)
     33 
     34 # l = [1,2,3,4]
     35 # l2 = l.__iter__()
     36 # while True:
     37 #     try:
     38 #         item = l2.__next__()
     39 #         print(item)
     40 #     except StopIteration:
     41 #         print('迭代完毕')
     42 #         break
     43 
     44 # 迭代器遵循迭代器协议:必须拥有__iter__方法和__next__方法
     45 
     46 # range()
     47 # print('__next__' in dir(range(12))) # False
     48 # print('__iter__' in dir(range(12))) # True
     49 
     50 # from collections import Iterator
     51 # print(isinstance(range(12),Iterator))   # False , 验证range执行之后得到的结果不是一个迭代器
     52 
     53 # 为何要有for循环
     54 
     55 # l = [1,2,3]
     56 # index = 0
     57 # while index < len(l):
     58 #     print(l[index])
     59 #     index += 1
     60 
     61 # 序列类型字符串,列表,元组都有下标,用上述方式访问,perfect!
     62 # 但是对于字典、集合、文件对象这种非序列型类型,就得使用for循环了。
     63 # for循环就是基于迭代器协议提供了一个统一的可以遍历所有对象的方法,
     64 # 即在遍历之前,先调用对象的__iter__方法将其转换成一个迭代器,
     65 # 然后使用迭代器去循环访问
     66 
     67 # 迭代器的好处是可以节省内存
     68 
     69 # print('__iter__' in dir(int))   # False
     70 # print('__iter__' in dir(bool))  # False
     71 # print('__iter__' in dir(list))  # True
     72 # print('__iter__' in dir(dict))  # True
     73 # print('__iter__' in dir(set))   # True
     74 # print('__iter__' in dir(tuple)) # True
     75 # print('__iter__' in dir(enumerate([]))) # True
     76 # print('__iter__' in dir(range(2))) # True
     77 # print('__next__' in dir(range(2))) # False
     78 # print('__next__' in dir(dict))  # False
     79 
     80 # g = range(10).__iter__()
     81 # print(g.__next__())
     82 # print(g.__next__())
     83 # print(g.__next__())
     84 # print(g.__next__())
     85 # print(g.__next__())
     86 # print(g.__next__())
     87 from collections import Iterator
     88 from collections import Iterable
     89 
     90 # class A:
     91 #     def __iter__(self): pass
     92 #     def __next__(self): pass
     93 #
     94 # a = A()
     95 # print(isinstance(a,Iterator))   # True
     96 # print(isinstance(a,Iterable))   # True
     97 
     98 # class A:
     99 #     def __iter__(self): pass
    100 #     #def __next__(self): pass
    101 #
    102 # a = A()
    103 # print(isinstance(a,Iterator))   # False
    104 # print(isinstance(a,Iterable))   # True    含有__iter__方法,是可迭代的,可迭代的,不一定是迭代器
    105 
    106 # class A:
    107 #     # def __iter__(self): pass
    108 #     def __next__(self): pass
    109 #
    110 # a = A()
    111 # print(isinstance(a,Iterator))   # False
    112 # print(isinstance(a,Iterable))   # False   不含有__iter__方法,是不可迭代的
    113 
    114 # 可以被for循环的都是可迭代的
    115 # 可迭代的内部都有__iter__方法
    116 # 只要是迭代器,一定可迭代
    117 # print(range(10).__iter__())
    118 
    119 # for
    120 # 只有可迭代对象才能用for
    121 # b = [].__iter__()
    122 # a = b.__iter__()
    123 # c = [].__iter__().__iter__()
    124 # print(b)
    125 # print(a)
    126 # print(c)
    View Code

    二、生成器

    # -*- encoding:utf-8 -*-
    
    # 在某些情况下,我们想要像迭代器那样节省内存,就只能自己写。
    # 我们自己写的这个能实现迭代器功能的东西就叫生成器
    
    # Python中提供的生成器:
    # 1.生成器函数:常规函数定义,但是使用yield语句返回结果,而不是return语句。
    #   yield语句一次返回一个结果,在那个结果中间,挂起函数的状态,以便下次从它离开的地方继续执行
    # 2.生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表
    # yield 和return不能共用
    
    # 初识生成器
    # import time
    # def generator_fun1():
    #     a = 1
    #     print('现在定义了a变量')
    #     yield a
    #     b = 2
    #     print('现在定义了b变量')
    #     yield b
    #
    # g1 = generator_fun1()   # generator_fun1() 返回一个可迭代的对象
    # print('g1: ',g1)    # g1: <generator object generator_fun1 at 0x00000250C7EBE4C0>
    #
    # print(next(g1))
    # time.sleep(1)
    # print(next(g1))
    # 输出:
    # 现在定义了a变量
    # 1
    # 现在定义了b变量
    # 2
    
    # 生成器好处:不会一下子在内存中生成太多数据
    
    
    # 初识生成器二
    # def produce():
    #     '''生成衣服'''
    #     for i in range(1,200):
    #         yield '生成了第%s件衣服'%i
    #
    # product_g = produce()
    # print(product_g.__next__())
    # print(product_g.__next__())
    # print(product_g.__next__())
    # num = 0
    # for i in product_g:
    #     print(i)
    #     num += 1
    #     if num == 5:
    #         break
    
    # 生成器监听文件输入????????????????????
    # import time
    # def tail(filename):
    #     f = open(filename,encoding='utf-8')
    #     f.seek(0,2) # 从文件末尾算起
    #     while 1:
    #         line = f.readline() # 读取文件中新的文本行
    #         if not line.strip():
    #             time.sleep(0.1)
    #             continue
    #         yield line.strip()
    # tail_g = tail('tmp')
    # for line in tail_g:
    #     print(line)
    
    # import time
    # def tail(filename):
    #     f = open(filename,encoding='utf-8')
    #     f.seek(0,2)
    #     while 1:
    #         line = f.readline().strip()
    #         if not line:
    #             time.sleep(0.1)
    #             continue
    #         yield line
    # tail_g = tail('tmp')
    # for line in tail_g:
    #     print(line)
    
    # 计算移动平均值
    # def averager():
    #     total = 0.0
    #     count = 0
    #     average = None
    #     while True:
    #         term = yield average
    #         total += term
    #         count += 1
    #         average = total/count
    #
    # g_avg = averager()
    # next(g_avg)
    # print(g_avg.send(10))# 先send一个值,再执行next函数
    # print(g_avg.send(30))
    # print(g_avg.send(50))
    
    # 计算移动平均值二
    # def init(func):
    #     def inner(*args,**kwargs):
    #         g = func(*args,**kwargs)
    #         next(g)
    #         return g
    #     return inner
    # @init
    # def averager():
    #     total = 0.0
    #     count = 0
    #     average = None
    #     while True:
    #         term = yield average
    #         total += term
    #         count += 1
    #         average = total/count
    #
    #
    # g_avg = averager()
    #
    # print(g_avg.send(10))
    # print(g_avg.send(30))
    # print(g_avg.send(50))
    
    # yield from
    # def gen1():
    #     for c in "AB":
    #         yield c
    #     for i in range(3):
    #         yield i
    # print(list(gen1())) # ['A', 'B', 0, 1, 2]
    #
    # def gen2():
    #     yield from 'AB'
    #     yield from range(3)
    # print(list(gen2())) # ['A', 'B', 0, 1, 2]
    
    #列表推导式和生成器表达式
    # egg_list = ['鸡蛋%s' %i for i in range(10)] # 列表解析
    # print(egg_list)
    #
    # laomuji = ('鸡蛋%s' %i for i in range(10)) # 生成器表达式
    # print(laomuji)
    # print(next(laomuji))    # next()本质就是调用__next__
    # print(laomuji.__next__())
    # print(next(laomuji))
    
    #总结
    # 1.把列表解析的[]换成()得到的就是生成器表达式
    # 2.列表解析与生成器表达式都是一种便利的编程方式,只不过生成器表达式更节省内存
    # 3.Python不但使用迭代器协议,让for循环变得更加通用。大部分内置函数,也是使用迭代器协议
    #   访问对象的。例如,sun函数是python的内置函数,该函数使用迭代器协议访问对象,而生成器实现了迭代器的协议,
    #   所以,我们可以直接这样计算一系列值的和:
    # print(sum(x ** 2 for x in range(4)))
    View Code

    三、生成器进阶练习

      1 # -*- encoding:utf-8 -*-
      2 # def generator():
      3 #     print(123)
      4 #     content = yield 1
      5 #     print('=====',content)
      6 #     print(456)
      7 #     arg = yield 2
      8 #     print(arg)
      9 #     yield
     10 
     11 # g1 = generator()
     12 # g2 = generator()
     13 # g1.__next__()
     14 # g2.__next__()
     15 # print('***',generator().__next__())
     16 # print('***',generator().__next__())
     17 
     18 # g = generator()
     19 # ret = g.__next__()
     20 # print(ret)
     21 # ret = g.send('hello')
     22 # print(ret)
     23 # print(g.send(1234))
     24 
     25 # send 获取下一个值的效果和next基本一致
     26 # 只是在获取下一个值的时候,给上一个yield的位置传递一个数据
     27 #使用send的注意事项
     28     # 第一次使用生成器的时候,是用next获取下一个值
     29     # 最后一个yield不能接受外部的值
     30 
     31 # def init(func):
     32 #     def inner(*args,**kwargs):
     33 #         g = func(*args,**kwargs)
     34 #         g.__next__()
     35 #         return g
     36 #     return inner
     37 # @init
     38 # def averager():
     39 #     sum = 0.0
     40 #     count = 0
     41 #     average = 0
     42 #     while 1:
     43 #         temp = yield average
     44 #         sum += temp
     45 #         count += 1
     46 #         average = sum/count
     47 # g = averager()
     48 # print(g.send(10))
     49 # print(g.send(30))
     50 # print(g.send(5))
     51 
     52 #yield from
     53 # def gnrator():
     54 #     a = 'AB'
     55 #     for i in a:
     56 #         yield i
     57 #     b = [1,2,3]
     58 #     for i in b:
     59 #         yield i
     60 # g = gnrator()
     61 # for i in g:
     62 #     print(i)
     63 
     64 # def gnrator2():
     65 #     yield from 'AB'
     66 #     yield from [1,2,3]
     67 # g = gnrator2()
     68 # for i in g:
     69 #     print(i)
     70 
     71 # 列表推导式
     72 # egg_list = ['egg%s' %i for i in range(10)]
     73 # print(egg_list)
     74 # print([i*i for i in range(1,10)])
     75 
     76 # 生成器表达式
     77 # g = (i for i in range(10)) #几乎不占用内存
     78 # print(g)
     79 # for i in g:
     80 #     print(i)
     81 
     82 # g2 = (i for i in range(20) if i%2 == 1)
     83 # for i in g2:
     84 #     print(i)
     85 
     86 # g3 = (i*i for i in range(10))
     87 # for i in range(10):
     88 #     print(g3.__next__())
     89 
     90 #各种推导式练习
     91 # names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
     92 #          ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
     93 # ret = [name for lst in names for name in lst if name.count('e') == 2]
     94 # print(ret)
     95 # 字典推导式
     96 # mcase = {'a': 10, 'b': 34, 'A': 7, 'Z': 3}
     97 # mcase2 = {k.lower(): mcase.get(k.lower(),0)+mcase.get(k.upper(),0) for k in mcase}
     98 # print(mcase2)
     99 # 集合推导式
    100 # sq = {x**2 for x in [1,-1,2]}
    101 # print(sq)
    View Code
  • 相关阅读:
    难以实践敏捷:估算
    使用AsyncEnumerator简化异步操作
    ESXi 入门配置
    学习模式,不如先了解问题
    我应该用哪种虚拟机?(一)
    在2003上实现Custom Task Pane
    我应该用哪种虚拟机?(终)
    我应该用哪种虚拟机?(二)
    正则表达式周二挑战赛 第十二周
    [译]Node中的ES6特性
  • 原文地址:https://www.cnblogs.com/liuyankui163/p/8185475.html
Copyright © 2011-2022 走看看