设为首页 加入收藏

TOP

python 生成器&迭代器(一)
2019-02-21 18:08:20 】 浏览:115
Tags:python 成器

一、生成器

1、列表生成器:列表生成式就像是一个厨师,他只会做这n(n为任意整数)道菜,想吃甚麽做甚麽,不吃不做,不浪费空间;而列表表达式就相当于已经做好的n盘菜,占用空间。
2、生成器的创建方法:

  • s = (x*2 for x in range(5))
  • yield+数字     只要有yield就是一个生成器对象

   第一种:

s = (x*2 for x in range(5))

print(next(s))       # 提取生成器里面的值,in python2中等价于 s._next_(),next() 一次打印一次
print(next(s))
print(next(s))

# 生成器就是一个可迭代对象(Iterable)
for i in s:         # 遍历生成器可迭代对象
    print(i)         # 打印完一个数之后这个数就被回收,不占用内存,只占用被引用值的哪一个内存

>>> 0  2  4  6  8

运行机制:从0开始,第一次next()时,取出一个数*2输出,然后每next()一次,取一个数,一直到2,for循环遍历时,因为前面next()已经取到了数字2的位置,所以从3开始,故输出为0 2 4 6 8

   第二种:

def fun():         # 注意:生成器对象是fun(),而不是fun
    print('s')
    yield 1

    print('ss')
    yield 2

g = fun()
print(g)           # <generator object fun at 0x000001D54E12A0F8>
 
next(g)            # 有返回值,为yield后的值
next(g)

解释:程序运行时先执行g = fun(), 执行到第一个next()时,返回到函数中执行具体内容,一直到执行完yield 1 停止,然后继续下一个next()再到函数中寻找yield 2 的内容,以此类推注意:如果再多一个next(g)就会报错:StopIteration(停止迭代),因为超过了迭代次数

什么是可迭代对象:内部有 _iter_() 的都是可迭代对象(列表、元组、字典)

def fun():   
    print('s')
    yield 1

    print('ss')
    yield 2

for i in fun():
    print(i)       # yield 有返回值,返回值赋给了i

>>>

s
1
ss
2

例1:输出斐波那契数列

def fib(maxs):
    n, before, after = 0, 0, 1
    while n < maxs:
        print(after)       # 从1开始,如打印before则从从0开始
        before, after = after, before+after      # 先计算后赋值(先右后左)
        n = n+1

fib(10)     # 输出前10个斐波那契数

注意:before, after = after, before+after  和 下面的两条语句不等价,原因见例1对应标注;

before = after
after =  before+after

例2:斐波那契数列生成器

def fib(maxs):
    n, before, after = 0, 0, 1
    while n < maxs:
        yield before
        before, after = after, before+after      # 先计算后赋值(先右后左)
        n = n+1

g = fib(8)
print(g)     # 生成器所在的内存地址

# 需要几个next() 几次,但最多不能超过8次,否则应修改fib() 里面的数字
print(next(g))
print(next(g))
print(next(g))
print(next(g))

3、 .send() 方法

def fun():        # fun()是一个生成器对象而不是fun
    print('qwer')
    count = yield 1       # 先把yield的值返回,然后把‘xss’赋值给变量count
    print(count)

    print('asdf')
    yield 2

f = fun()
# next(f)        # 进入函数体
f.send(None)          # next(f)  第一次send前如果没有next,只能传一个send(None),因为没有进入到函数体,否则报错,
# TypeError: can't send non-None value to a just-started generator
s = f.send('xss')      # 给yield前面的变量赋值
print(s)    # s 是yield 2 的返回值

例3:yield 伪并发的实现

import time

def consumer(name):
    print("%s准备吃包子!" % name)
    while True:
        baozi = yield
        print("包子[%s]来了,被[%s]吃了!" % (baozi, name))

def producer(name):
    a1 = consumer('A')
    a2 = consumer('B')
    next(a1)
    next(a2)
    print("%s准备吃包子了!" % name)
    for i in range(5):
        time.sleep(1)
        print("做了2个包子")
        a1.send(i)
        a2.send(i)

producer("xiaoss")
>>>

      A准备吃包子!
      B准备吃包子!
      xiaoss准备吃包子了!
      做了2个包子
      包子[0]来了,被[A]吃了!
      包子[0]来了,被[B]吃了!
      做了2个包子
      包子[1]来了,被[A]吃了!
      包子[1]来了,被[B]吃了!
      做了2个包子
      包子[2]来了,被[A]吃了!
      包子[2]来了,被[B]吃了!
      做了2个包子
      包子[3]来了,被[A]吃了!
      包子[3]来了,被[B]吃了!
      做了2个包子
      包子[4]来了,被[A]吃了!
   &nbs

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇聊一聊,这些年我用Python爬虫挣.. 下一篇用python实现新词发现程序——基..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目