zoukankan      html  css  js  c++  java
  • python全栈开发从入门到放弃之迭代器生成器

    1、python中的for循环

     1 l = [1,2,3,4,5,6]
     2 for i in l:          #根据索引取值
     3     print(i)
     4 
     5 输出结果:
     6 
     7 1
     8 2
     9 3
    10 4
    11 5
    12 6

    2、iterable  可迭代的

    可迭代的数据类型有哪些

    str
    列表
    tuple   元组
    set      集合
    dict     字典

    print(dir([1,2]))
    print(dir((2,3)))
    print(dir({1:2}))
    print(dir({1,2}))
    
    
    输出结果:
    ['__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']
    ['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'count', 'index']
    ['__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']
    ['__and__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__iand__', '__init__', '__init_subclass__', '__ior__', '__isub__', '__iter__', '__ixor__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__or__', '__rand__', '__reduce__', '__reduce_ex__', '__repr__', '__ror__', '__rsub__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__xor__', 'add', 'clear', 'copy', 'difference', 'difference_update', 'discard', 'intersection', 'intersection_update', 'isdisjoint', 'issubset', 'issuperset', 'pop', 'remove', 'symmetric_difference', 'symmetric_difference_update', 'union', 'update']

    3、可迭代的 ——对应的标志  __iter__

    1 print('__iter__' in dir([1,2,3]))      #判断一个变量是否是可迭代的以布尔值的形式返回回来
    2 dir查看变量的内置函数
    3 
    4 输出结果:
    5 True

    4、可迭代协议 iter

    我们现在是从结果分析原因,能被for循环的就是“可迭代的”,但是如果正着想,for怎么知道谁是可迭代的呢?

    假如我们自己写了一个数据类型,希望这个数据类型里的东西也可以使用for被一个一个的取出来,那我们就必须满足for的要求。这个要求就叫做“协议”。

    可以被迭代要满足的要求就叫做可迭代协议。可迭代协议的定义非常简单,就是内部实现了__iter__方法。

     

    5、

    迭代器协议

    既什么叫“可迭代”之后,又一个历史新难题,什么叫“迭代器”?

    虽然我们不知道什么叫迭代器,但是我们现在已经有一个迭代器了,这个迭代器是一个列表的迭代器。

    我们来看看这个列表的迭代器比起列表来说实现了哪些新方法,这样就能揭开迭代器的神秘面纱了吧?

     1 '''
     2 dir([1,2].__iter__())是列表迭代器中实现的所有方法,dir([1,2])是列表中实现的所有方法,都是以列表的形式返回给我们的,为了看的更清楚,我们分别把他们转换成集合,
     3 然后取差集。
     4 '''
     5 #print(dir([1,2].__iter__()))
     6 #print(dir([1,2]))
     7 print(set(dir([1,2].__iter__()))-set(dir([1,2])))
     8 
     9 结果:
    10 {'__length_hint__', '__next__', '__setstate__'}

    6、__length_hint__', '__next__', '__setstate__

    iter_l = [1,2,3,4,5,6].__iter__()
    
    print(iter_l)
    
    输出结果:
    <list_iterator object at 0x000002A9A6BA99B0>
    
    
    iter_l = [1,2,3,4,5,6,7,8].__iter__()
    #获取迭代器元素的长度
    print(iter_l.__length_hint__())
    输出结果
    8
    
    #根据索引值在哪里开始迭代
    print('*',iter_l.__setstate__(4))
    
    #一个一个取值
    print('**',iter_l.__next__())
    print('***',iter_l.__next__())
    输出结果:
    8
    * None
    ** 5
    *** 6

    7、不用for循环来取值

    l = [1,2,3,4]
    l_iter = l.__iter__()
    print(next(l_iter))
    print(next(l_iter))
    print(next(l_iter))
    print(next(l_iter))
    print(next(l_iter))      
    
    Traceback (most recent call last):
    1
      File "F:/python/python全栈开发/day17/s3.py", line 7, in <module>
    2
        print(next(l_iter))
    3
    StopIteration
    4

    但是遍历迭代器里没有了的值会报错所以需要一个报错机制来预防

    l = [1,2,3,4]
    l_iter = l.__iter__()
    while True:
        try:                           #try当下面代码出现异常会执行下面except
            item = l_iter.__next__()
            print(item)
        except StopIteration:          #except 出现了异常会不报错直接跳出循环
            break
    
    
    输出结果:
    1
    2
    3
    4

    8、查看一个是否是迭代器还是可迭代对象

    1 print('__next__' in dir(range(12)))  #查看'__next__'是不是在range()方法执行之后内部是否有__next__
    2 print('__iter__' in dir(range(12)))  #查看'__next__'是不是在range()方法执行之后内部是否有__next__
    3 
    4 from collections import Iterator
    5 print(isinstance(range(100000000),Iterator))  #验证range执行之后得到的结果不是一个迭代器

    False
    True
    False

     

    初识生成器

    我们知道的迭代器有两种:一种是调用方法直接返回的,一种是可迭代对象通过执行iter方法得到的,迭代器有的好处是可以节省内存。

    如果在某些情况下,我们也需要节省内存,就只能自己写。我们自己写的这个能实现迭代器功能的东西就叫生成器。

     

    Python中提供的生成器:

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

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

    生成器Generator:

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

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

    生成器函数

     1 import time
     2 def genrator_fun1():
     3     a = 1
     4     print('现在定义了a变量')
     5     yield a                    
     6     b = 2
     7     print('现在定义了b变量')
     8     yield b
     9 
    10 g1 = genrator_fun1()           #传回了一个生成器
    11 print('g1: ',g1)               #可以看到g1就是一个生成器
    12 print('_'*20)                  #华丽的分割线
    13 print(next(g1))                #看到next启用了生成器
    14 time.sleep(1)
    15 print(next(g1))                #在启用一次生成器输出b
    16 
    17 
    18 输出结果:
    19 g1:  <generator object genrator_fun1 at 0x000001F523C7B258>
    20 ____________________
    21 现在定义了a变量
    22 1
    23 现在定义了b变量
    24 2

    生成器有什么好处呢?就是不会一下子在内存中生成太多数据

    假如我想让工厂给学生做校服,生产2000000件衣服,我和工厂一说,工厂应该是先答应下来,然后再去生产,我可以一件一件的要,也可以根据学生一批一批的找工厂拿。
    而不能是一说要生产2000000件衣服,工厂就先去做生产2000000件衣服,等回来做好了,学生都毕业了。。。

    def produce():
        """生产衣服"""
        for i in range(1,2000000):
            yield "生产了第%s件衣服"%i
    
    func=produce()               #拿到一个生成器
    print(func.__next__())       #要一件衣服
    print(func.__next__())       #在要一件衣服
    
    num=0
    for i in func:               #要一批衣服
        print(i)
        num+=1
        if num==5:
            break
    
    生产了第1件衣服
    生产了第2件衣服
    生产了第3件衣服
    生产了第4件衣服
    生产了第5件衣服
    生产了第6件衣服
    生产了第7件衣服
    
    
    想要多少衣服就取多少衣服
     1 import time
     2 
     3 
     4 def tail(filename):
     5     f = open(filename)
     6     f.seek(0, 2) #从文件末尾算起
     7     while True:
     8         line = f.readline()  # 读取文件中新的文本行
     9         if not line:
    10             time.sleep(0.1)
    11             continue
    12         yield line
    13 
    14 tail_g = tail('tmp')
    15 for line in tail_g:
    16     print(line)
     1 def averager():
     2     total = 0.0
     3     count = 0
     4     average = None
     5     while True:
     6         term = yield average
     7         total += term
     8         count += 1
     9         average = total/count
    10 
    11 
    12 g_avg = averager()
    13 next(g_avg)
    14 print(g_avg.send(10))
    15 print(g_avg.send(30))
    16 print(g_avg.send(5))
     1 def init(func):  #在调用被装饰生成器函数的时候首先用next激活生成器
     2     def inner(*args,**kwargs):
     3         g = func(*args,**kwargs)
     4         next(g)
     5         return g
     6     return inner
     7 
     8 @init
     9 def averager():
    10     total = 0.0
    11     count = 0
    12     average = None
    13     while True:
    14         term = yield average
    15         total += term
    16         count += 1
    17         average = total/count
    18 
    19 
    20 g_avg = averager()
    21 # next(g_avg)   在装饰器中执行了next方法
    22 print(g_avg.send(10))
    23 print(g_avg.send(30))
    24 print(g_avg.send(5))
     1 def gen1():
     2     for c in 'AB':
     3         yield c
     4     for i in range(3):
     5         yield i
     6 
     7 print(list(gen1()))
     8 
     9 def gen2():
    10     yield from 'AB' 
    11     yield from range(3)
    12 
    13 print(list(gen2()))

    列表推导式和生成器表达式

    #老男孩由于峰哥的强势加盟很快走上了上市之路,alex思来想去决定下几个鸡蛋来报答峰哥
    
    egg_list=['鸡蛋%s' %i for i in range(10)] #列表解析
    
    #峰哥瞅着alex下的一筐鸡蛋,捂住了鼻子,说了句:哥,你还是给我只母鸡吧,我自己回家下
    
    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循环变得更加通用。大部分内置函数,也是使用迭代器协议访问对象的。例如, sum函数是Python的内置函数,该函数使用迭代器协议访问对象,而生成器实现了迭代器协议,所以,我们可以直接这样计算一系列值的和:

    本章小结

    可迭代对象:

      拥有__iter__方法

      特点:惰性运算

      例如:range(),str,list,tuple,dict,set

    迭代器Iterator

      拥有__iter__方法和__next__方法

      例如:iter(range()),iter(str),iter(list),iter(tuple),iter(dict),iter(set),reversed(list_o),map(func,list_o),filter(func,list_o),file_o

    生成器Generator:

      本质:迭代器,所以拥有__iter__方法和__next__方法

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

    使用生成器的优点:

    1.延迟计算,一次返回一个结果。也就是说,它不会一次生成所有的结果,这对于大数据量处理,将会非常有用

     

    可迭代协议  :  内部实现了__iter__方法

     

    迭代器协议  :  内部实现了__iter__ __next__方法

     

    可迭代和迭代器的不同点 : 迭代器多实现了一个__next__方法

     

    可迭代和迭代器的相同点 : 都可以用for循环

     

    判断迭代器和可迭代的方法

    第一种:判断内部是不是实现了 __next__

    '__next__' in dir(o)

     

    第二种:

    from collections import Iterable  #可迭代

     from collections import Iterator  #迭代器

    isinstance(o,Iterable)

     isinstance(o,Iterator)

     

    迭代器的特点

    可以用for循环

    可以节省内存

     

    你只能用一次  l = [1,2,3,4]

    1 #列表解析
    2 sum([i for i in range(100000000)])#内存占用大,机器容易卡死
    3  
    4 #生成器表达式
    5 sum(i for i in range(100000000))#几乎不占内存

    生成器相关的面试题

    生成器在编程中发生了很多的作用,善用生成器可以帮助我们解决很多复杂的问题

    除此之外,生成器也是面试题中的重点,在完成一些功能之外,人们也想出了很多魔性的面试题。
    接下来我们就来看一看~

     1 def demo():
     2     for i in range(4):
     3         yield i
     4 
     5 g=demo()
     6 
     7 g1=(i for i in g)
     8 g2=(i for i in g1)
     9 
    10 print(list(g1))      #g1已经把列表的值取完了
    11 print(list(g2))       #所以g2取的是空列表

    假如我现在有一个列表l=['a','b','c','d','e'],我想取列表中的内容,有几种方式?

    首先,我可以通过索引取值l[0],其次我们是不是还可以用for循环来取值呀?

    你有没有仔细思考过,用索引取值和for循环取值是有着微妙区别的。

    如果用索引取值,你可以取到任意位置的值,前提是你要知道这个值在什么位置。

    如果用for循环来取值,我们把每一个值都取到,不需要关心每一个值的位置,因为只能顺序的取值,并不能跳过任何一个直接去取其他位置的值。

    但你有没有想过,我们为什么可以使用for循环来取值?

    for循环内部是怎么工作的呢?

    python中的for循环

    要了解for循环是怎么回事儿,咱们还是要从代码的角度出发。

    首先,我们对一个列表进行for循环。

    for i in [1,2,3,4]:  
        print(i)

    上面这段代码肯定是没有问题的,但是我们换一种情况,来循环一个数字1234试试

    复制代码
    for i in 1234
        print(i) 
    
    结果:
    Traceback (most recent call last):
      File "test.py", line 4, in <module>
        for i in 1234:
    TypeError: 'int' object is not iterable
    复制代码

    看,报错了!报了什么错呢?“TypeError: 'int' object is not iterable”,说int类型不是一个iterable,那这个iterable是个啥?

    假如你不知道什么是iterable,我们可以翻翻词典,首先得到一个中文的解释,尽管翻译过来了你可能也不知道,但是没关系,我会带着你一步一步来分析。

    迭代和可迭代协议

    什么叫迭代

    现在,我们已经获得了一个新线索,有一个叫做“可迭代的”概念

    首先,我们从报错来分析,好像之所以1234不可以for循环,是因为它不可迭代。那么如果“可迭代”,就应该可以被for循环了。

    这个我们知道呀,字符串、列表、元组、字典、集合都可以被for循环,说明他们都是可迭代的

    我们怎么来证明这一点呢?

    复制代码
    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))
    复制代码

    结合我们使用for循环取值的现象,再从字面上理解一下,其实迭代就是我们刚刚说的,可以将某个数据集内的数据“一个挨着一个的取出来”,就叫做迭代

    可迭代协议

    我们现在是从结果分析原因,能被for循环的就是“可迭代的”,但是如果正着想,for怎么知道谁是可迭代的呢?

    假如我们自己写了一个数据类型,希望这个数据类型里的东西也可以使用for被一个一个的取出来,那我们就必须满足for的要求。这个要求就叫做“协议”。

    可以被迭代要满足的要求就叫做可迭代协议。可迭代协议的定义非常简单,就是内部实现了__iter__方法。

    接下来我们就来验证一下:

    print(dir([1,2]))
    print(dir((2,3)))
    print(dir({1:2}))
    print(dir({1,2}))
    复制代码
    ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__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']
    ['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'count', 'index']
    ['__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']
    ['__and__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__iand__', '__init__', '__ior__', '__isub__', '__iter__', '__ixor__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__or__', '__rand__', '__reduce__', '__reduce_ex__', '__repr__', '__ror__', '__rsub__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__xor__', 'add', 'clear', 'copy', 'difference', 'difference_update', 'discard', 'intersection', 'intersection_update', 'isdisjoint', 'issubset', 'issuperset', 'pop', 'remove', 'symmetric_difference', 'symmetric_difference_update', 'union', 'update']
    复制代码

    总结一下我们现在所知道的:可以被for循环的都是可迭代的,要想可迭代,内部必须有一个__iter__方法。

    接着分析,__iter__方法做了什么事情呢?

    print([1,2].__iter__())
    
    结果
    <list_iterator object at 0x1024784a8>

    执行了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__方法。

    还账:next和iter方法

    如此一来,关于迭代器和生成器的方法我们就还清了两个,最后我们来看看range()是个啥。首先,它肯定是一个可迭代的对象,但是它是否是一个迭代器?我们来测试一下

    print('__next__' in dir(range(12)))  #查看'__next__'是不是在range()方法执行之后内部是否有__next__
    print('__iter__' in dir(range(12)))  #查看'__next__'是不是在range()方法执行之后内部是否有__next__
    
    from collections import Iterator
    print(isinstance(range(100000000),Iterator))  #验证range执行之后得到的结果不是一个迭代器

     

     

    为什么要有for循环

    基于上面讲的列表这一大堆遍历方式,聪明的你立马看除了端倪,于是你不知死活大声喊道,你这不逗我玩呢么,有了下标的访问方式,我可以这样遍历一个列表啊

    复制代码
    l=[1,2,3]
    
    index=0
    while index < len(l):
        print(l[index])
        index+=1
    
    #要毛线for循环,要毛线可迭代,要毛线迭代器
    复制代码

    没错,序列类型字符串,列表,元组都有下标,你用上述的方式访问,perfect!但是你可曾想过非序列类型像字典,集合,文件对象的感受,所以嘛,年轻人,for循环就是基于迭代器协议提供了一个统一的可以遍历所有对象的方法,即在遍历之前,先调用对象的__iter__方法将其转换成一个迭代器,然后使用迭代器协议去实现循环访问,这样所有的对象就都可以通过for循环来遍历了,而且你看到的效果也确实如此,这就是无所不能的for循环,觉悟吧,年轻人

     

     

    初识生成器

    我们知道的迭代器有两种:一种是调用方法直接返回的,一种是可迭代对象通过执行iter方法得到的,迭代器有的好处是可以节省内存。

    如果在某些情况下,我们也需要节省内存,就只能自己写。我们自己写的这个能实现迭代器功能的东西就叫生成器。

     

    Python中提供的生成器:

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

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

    别想一下造出大海,必须先由小河川开始。
  • 相关阅读:
    MSSQL大量数据时,建立索引或添加字段后保存更改超时该这么办
    POJ 3261 Milk Patterns (后缀数组)
    POJ 1743 Musical Theme (后缀数组)
    HDU 1496 Equations (HASH)
    694. Distinct Substrings (后缀数组)
    POJ 1222 EXTENDED LIGHTS OUT (枚举 或者 高斯消元)
    POJ 1681· Painter's Problem (位压缩 或 高斯消元)
    POJ 1054 The Troublesome Frog (hash散列)
    HDU 1716 排列2
    HDU 4405 Aeroplane chess (概率DP & 期望)
  • 原文地址:https://www.cnblogs.com/zcfx/p/7275472.html
Copyright © 2011-2022 走看看