迭代器和生成器

今天主要内容:

  1.迭代器

  2.生成器

一.迭代器

  可以使用dir()函数来检查类的内部定义的函数;

  s = "adjlafk"

  print(dir(s))    #可以打印对象中的方法和函数

  print(dir(str))  #也可以打印类中声明的方法和函数

在打印结果中,寻找__iter__如果能找到,那么这个类的对象就是一个可迭代对象.

for循环的东西都有__iter__函数,包括range也有.如果对象中有__iter__函数.那么我们认为这个对像遵守了可迭代协议.就可以进行迭代.这里的__iter__是帮助我们获取到对象的迭代器.我们使用__next__()来获取到一个迭代器中的元素.

下面我们来看看for循环的工作原理是什么?

s = "我爱北京天安门"

c = s.__iter__()  #获取迭代器

print(c.__next__())  #使用迭代器进行迭代,获取一个元素     我

print(c.__next__())  #爱

print(c.__next__())  #北

print(c.__next__())  #京

print(c.__next__())  #天

print(c.__next__())  #安

print(c.__next__())  #门

print(c.__next__())  #StopIteration     (报错)

当程序遇到StopIteration将结束循环

for循环要求必须是可迭代对象

for循环的内部,使用的就是迭代器.最开始的时候就是获取迭代器.

二.生成器

  生成器实质就是迭代器.

  在Python中有三种方式来获取生成器:

  1.通过生成器函数

  2.通过各种推导式来实现生成器

  3.通过数据的转换也可以获取生成器.

今天我们主要使用生成器函数来完成生成器的创建和使用.

首先,我们先看一个很简单的函数:

def func():

  print("111")

  return 222

ret = func()

print(ret)

结果是:111    222

将函数中的return换成yield就是生成器

def  func():

  print("111")

  yield 222

ret = func()

print(ret)

结果:<generator  object  func at 0x10567ff68>#内存地址

运行的结果和上面不一样,由于函数中存在了yield,那么这个函数就是一个生成器函数.这个时候,我们在执行这个函数的时候.就不再是函数的执行了.而是获取这个生成器.生成器的本质就是迭代器,所以我们直接执行__next__()来执行一下生成器.

def func():

  print("111")

  yield 222

gener = func()  #这个时候函数不会执行,而是获取到生成器

ret = gener.__next__()  #这个时候函数才会执行,yield的作用和return一样,也是返回数据.

print(ret)

结果:111    222

拿到生成器之后,就相当于拿到了迭代器.  __next__()的作用是执行到下一个yield.

yield和return的区别:

1.如果函数中包含了yield,这个函数是一个生成器函数;执行函数的时候是:生成器.

2.生成器执行__next__(),执行到下一个yield.

3.yield的作用和return基本相同,但是只负责返回,不会结束函数.

4.return是结束函数.

好了到此生成器说完了,但是生成器有什么作用呢?我们看这样一个需求:一个公司向厂家订购了10000套工作服.

def  cloth():

  lst = []

  for i in range(10000):

    lst.append("衣服"+str(i))

  return  lst

ret = cloth()

这样操作的话,厂家会把一万套衣服一次性给我;这样的话我一下用不完,而且多余的也没有地方放.如果能一套一套的给我就好了.

def  cloth():

  for i in range(10000):

    yield "衣服"+str(i)

ret = cloth()

print(ret.__next__())

print(ret.__next__())

print(ret.__next__())....

或者:

for i in range(50):

  print(ret.__next__())

区别:第一种是直接一次性全部拿出来,会很占用内存.第二种使用生成器,一次就一个,用多少生成多少.生成器是一个一个的指向下一个.不会回去,__next__()到哪,指针就指到哪.下一次继续获取指针指向的值.

生成器和迭代器最大的优点就是节省内存,如果函数的最后没有yield,则会报错.

send()和__next__()一样,也是执行到下一个yield.

def eat():

  print("我吃什么啊")

  a = yield "包子"

  print(a)

  b = yield "大饼"

  print(b)

  print("程序结束")

  yield "GAME OVER"

gen = eat()  #获取生成器

ret = gen.__next__()

print(ret)

ret1 = gen.send("胡辣汤")

print(ret1)

ret2 = gen.send("羊肉泡馍")

print(ret2)

注意:第一次调用必须使用__next__()

send和__next__()区别:

1.send和__next__()都是让生成器向下走一次

2.send可以改上一个yield的位置传递值,不能给最后一个yield发送值.在第一次执行生成器代码的时候不能使用send()只能使用__next__()

生成器的优点:节省内存.

  

 

posted @ 2018-06-19 12:45  冯坤大神  阅读(73)  评论(0编辑  收藏  举报