码迷,mamicode.com
首页 > 编程语言 > 详细

Python生成器

时间:2017-10-02 18:53:55      阅读:194      评论:0      收藏:0      [点我收藏+]

标签:while   函数   访问   元素   stop   开始   max   oms   存储空间   

生成器就是一个可迭代对象

通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。

所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。

要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator:

 

生成器创建1

s=(i for i in range(5))

生成器创建2

def foo():
    yield 1
print(foo()) #<generator object foo at 0x00000106B374ECA8> |加括号说明执行生成器
print(foo) #<function foo at 0x0000024E5E3F3E18>
|不加括号说明执行函数


 

生成器的使用next方法

def foo():
    print(1)
    yield 1    #第一个next进来,发现yield后类似return返回值并退出
    print(2)
    yield 2    #第二个next进来,发现yield后类似return返回值并退出
f=foo() 
print(next(f))
print(next(f))
print(next(f))  #没有yield所以报错StopIteration

改进:
def foo():
    print(1)
    yield 1    #第一个next进来,发现yield后类似return返回值并退出
    print(2)
    yield 2    #第二个next进来,发现yield后类似return返回值并退出

f=foo() 
for i in f: #说明f是可迭代对象,会自动调用next,遇到StopIteration会自动退出
  print(i)

所以,我们创建了一个generator后,基本上永远不会调用next(),而是通过for循环来迭代它,并且不需要关心StopIteration的错误。

generator非常强大。如果推算的算法比较复杂,用类似列表生成式的for循环无法实现的时候,还可以用函数来实现。

 

可迭代对象:拥有iter方法

list

tuple

dict

string

 

斐波那契数列

用函数实现:

1 def fib(max):
2     n, a, b = 0, 0, 1
3     print(a)
4     while n < max:
5         print(b)
6         a, b = b, a + b
7         n = n + 1
8     return done

 

用列表生成式yield实现


def fib(max):
n, a, b = 0, 0, 1
print(a)
while n < max:
yield b #yield保存了上次执行的地点
a, b = b, a + b
n = n + 1
return ‘done‘
f=fib(5)
for i in f:
print(i)
 

这里,最难理解的就是generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。

send赋值

 1 def foo():
 2     print(a)  #这儿是第一次next进来输出的
 3     t1=yield 1  #遇到yield就像遇到return一样,退出返回值
 4     print(b)
 5     t2=yield 2
 6 
 7 f=foo()
 8 next(f)  #send第一次必须有一个next让他进门
 9 #f.send(None)==next(f)
10 ret=f.send(aa)     #这里的aa会赋值给t1
11 print(ret)

 

yield实现在单线程的情况下实现并发运算的效果

import time
def customs(n):
    print(%s准备吃包子了%n)
    while True:
        baozi=yield
        print(%s吃了包子%s%(n,baozi))
def boss(z):
    a=customs(a)
    b=customs(b)
    next(a)
    next(b)
    print(%s开始做包子了!%z)
    for i in range(10):
        time.sleep(1)
        print(包子做好了!)
        a.send(i)
        b.send(i)

boss(xiaoyaz)

 

Python生成器

标签:while   函数   访问   元素   stop   开始   max   oms   存储空间   

原文地址:http://www.cnblogs.com/xiaoyaz/p/7620547.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!