zoukankan      html  css  js  c++  java
  • Python生成器

    简单的生成器,生成器解析式:

    1 #usr/bin/env python3
    2 # -*- codign=utf-8 -*-
    3 
    4 myGenerator = (x*x for x in range(10)) #简单的生成器
    5 print(type(myGenerator)) #输出<class 'generator'>
    6 print(dir(myGenerator)); #输出:['__class__', '__del__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__name__', '__ne__', '__new__', '__next__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'close', 'gi_code', 'gi_frame', 'gi_running', 'gi_yieldfrom', 'send', 'throw']

    dir()发现里面发现有迭代器中的__iter__()和__next__(),这说明myGenerator是迭代器,是迭代器就可以用for循环。

    1 #既然有迭代器的属性就可以用next()循环读取
    2 print("First number: ", next(myGenerator)) #First number:  0
    3 print("Second Number: ", next(myGenerator)) #Second Number:  1
    4 
    5 #循环读取余下的
    6 for i in myGenerator:
    7     print(i) #输出1-10的平方的结果

    再看熟知的list:

     1 myList = [x*x for x in range(10)]; #定义列表解析式
     2 print(type(myList)) #输出:<class 'list'>
     3 print(dir(myList)) ##['__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']
     4 
     5 #print(next(myList)) #出错:TypeError: 'list' object is not an iterator,说明不可迭代
     6 #第一次循环有输出
     7 for i in myList:
     8     print(i) #有输出
     9 #第二次循环还是有输出
    10 for j in myList:
    11     print(j) #有输出

    总结:

    1,生成器在第一次循环的时候,将myGenerator里的值依次读取并打印,再次读取的,就发现没有任何结果了。迭代器所具有的特性。这与列表不同。

    2,生成器解析在很多地方都可以替代列表解析,因为,它占用内存少。

    3,代码优雅简洁。如下:

    1 sum(i*i for i in range(10)) #生成器
    2 sum([i*i for i in range(10)]) #列表解析

    yield,真正的生成器利器。

     1 def myGenerator():
     2     yield 0
     3     yield 1
     4     yield 2
     5 
     6 myGenerator = myGenerator()
     7 print(myGenerator) #输出:<generator object myGenerator at 0x7fa02fdedac0>
     8 print(type(myGenerator)) #输出:<class 'generator'>
     9 print(dir(myGenerator)) #输出有:__iter__()和__next__()说明是迭代器
    10 print(next(myGenerator)) #输出0
    11 print(next(myGenerator)) #输出1
    12 print(next(myGenerator)) #输出2
    13 print(next(myGenerator)) #读取完了,错误提示,发起StopIteration

    也就是说,这个含有yeild关键词的函数myGenerator返回值是一个生成器类型的对象。而这个生成器就是迭代器。也可以把含有yeild语句的函数叫做生成器。是一种用普通函数语法定义的迭代器。上例函数解析:

    1. myGenerator = myGenerator()。调用函数并把它赋值给变量myGenerator,除了返回生成器外什么都没有做,任何值都不会返回。
    2. print(myGenerator)。打印一下对象,说明是生成器类型。
    3. print(type(myGenerator))。查看类型。
    4. print(dir(myGenerator))。还是查看。
    5. print(next(myGenerator))。生成器开始执行,遇到第一个yeild语句,将值返回并暂停执行(有的称之为挂起)。
    6. print(next(myGenerator))。再次调用next(),从上次暂停的位置开始,将值返回,并暂停。
    7. print(next(myGenerator))。重复上面操作。
    8. print(next(myGenerator))。重复上面操作。

    执行过程:yeild除了作为生成器的标志之外,还有一个功能就是返回值。既然是返回值,那么在函数内部跟return有什么区别?

    首先看return:

    1 def checkReturn():
    2     print "Begin......"
    3     while n > 0:
    4         print("Before return.")
    5         return n
    6         n -= 1
    7         print("After return.")
    8 a = checkReturn(3) #输出了函数体内的第一个和第二个print语句:Begin...... Before return.
    9 print(a) #执行函数体内的return n 语句,输出3

    上面的代码并没有执行函数体内return语句后面的语句,也就是函数体内遇到return后只执行return语句,return语句后面的代码都不执行。

    再看yeild:

     1 def checkYeild(n):
     2     print("Begin to check yield.....")
     3     while n > 0:
     4         print("Before yeild.")
     5         yield n
     6         n -= 1
     7         print("After yeild")
     8 
     9 b = checkYeild(3) #调用函数checkYeild,除了返回生成器什么都不做
    10 print("First time to call: ", next(b)) #遇到yeild,返回值,暂停。
    11 print("Second time to call: ", next(b))  #从上次暂停位置继续执行
    12 print("Third time to call: ", next(b)) #又遇到yeild,返回值,暂停。
    13 print("Forth time to call: ", next(b)) #第四次调用的时候,发现n已经不满足条件while n>0了,发起StopIteration

    用生成器些斐波那契数列:

     1 def fibs(fmax):
     2     '''
     3     Generator for fibonacci sequence
     4     '''
     5     n, a, b = 0, 0, 1
     6     while n < fmax:
     7         yield b
     8         a,b = b, a+b
     9         n = n + 1
    10 
    11 if __name__ == "__main__":
    12     fs = fibs(10)
    13     for i in fs:
    14         print(i)

    生成器yeild还有几个方法:send(),throw(),close()。以后再说。

    
    
    
  • 相关阅读:
    JS 提交表单
    [ZJOI 2010]base 基站选址
    [ZJOI 2013]丽洁体
    [Codeforces 176B]Word Cut
    [SDOI 2013]方程
    [AtCoder agc021D]Reversed LCS
    [BZOJ 4361]isn
    [SDOI 2011]黑白棋
    [ZJOI 2010]Perm 排列计数
    [Codeforces 297E]Mystic Carvings
  • 原文地址:https://www.cnblogs.com/mafu/p/13540341.html
Copyright © 2011-2022 走看看