列表生成器及其方法

29 篇文章 0 订阅

一.列表生成式

列表生成式是Python 内置的非常简单却强大的可以用来创建 list的生成式

求出1-9的平方数,


print [ i**2 for i in range(1,10) if i !=0 ]



执行结果

[1234567]

list=[i for i in range(1,8)]

```
list= [1,2,3,4,5,6,7]

二.生成器

通过列表生成式,我们可以直接创建一个列表,受到内存限制,列表容量肯定是有限的;创建一个包含1万或者更多的元素的列表,占用很大的存储空间;而列表生成器可以很好地解决这个问题

这里写图片描述

1.生成器是什么?

在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的 list,从而节省大量的空间。在 Python 中,这种一边循环一边计算的机制,称为生成器(Generator)
这里写图片描述
那如果要取第8888个元素呢?for 循环,if

In [19]: for i in li:
   ....:     if i == 8888:
   ....:         print i
   ....:         
8888

2.怎么创建生成器?

把一个列表生成式的 [] 改成 ()
使用g.next()方法依次读取元素(麻烦)
使用 for 循环(推荐)

2.1列表转化生成器方法一迭代器: iter(*)
li = [ 1,2,3,4]
print type(li)
g = iter(li)
print type(g)

执行结果li列表被转化生成器g了

<type 'list'>
<type 'listiterator'>
2.2方法二 *.__iter__()
ls = range(4)
print type(ls)
g = ls.__iter__()
print type(g)

查看类型,转化成了生成器

<type 'list'>
<type 'listiterator'>

定义一个列表

li = [ i for i in range(5)]
print li
print type(li),

执行结果:

[0, 1, 2, 3, 4]
<type 'list'>

三.生成器的一些方法

1.next()方法查看元素
li = ( i for i in range(5))
print li           ##打印出的是生成器地址
print type(li)     ##查看li的类型为'generator'
print next(li)     ##第一次遍历元素 0
print li.next()    ##第二次遍历元素 1
print li.next()    ##第三次遍历元素 2
print li.next()    ##第四次遍历元素 3
print li.next()    ##第五次遍历元素 4
print li.next()    ##第六次因为元素已经遍历完了所以会抛出异常StopIteration

执行结果

<generator object <genexpr> at 0x7f8272d5eb40>   ##生成器地址
<type 'generator'>     ##类型为生成器
0
1
2
3
4
Traceback (most recent call last):
  File "/home/kiosk/PycharmProjects/3.16/3.17.py", line 511, in <module>
    print li.next()
StopIteration
2.close()方法关闭生成器
g = ( i for i in range(5))
print next(g)        ##第一次输出结果为0
print g.next()       ##第二次为1
print g.next()       ##第三次为2
g.close()            ##第三次之后关闭,终止生成器
print g.next()       ##所以这次以及以后会报错StopIteration

执行结果

0
1
2
Traceback (most recent call last):
  File '/home/kiosk/PycharmProjects/3.16/3.17.py', line 509, in <module>
    print g.next()
StopIteration

对于生成器g

g = ( i for i in range(5))
while 1:
    try:
        print g.next()
    except StopIteration:
        print '生成器元素没了'
        break

执行结果

0
1
2
3
4
生成器元素没了
3.yield:
    # 函数中如果有yield, 那么调用这个函数的返回值为生成器。
# 当生成器g调用next方法, 执行函数, 直到遇到yield就停止;
# 再执行next,从上一次停止的地方继续执行;
# 函数中遇return直接退出, 不继续执行后面代码;当函数中出现yield则默认该函数为生成器,
throw 给生成器发送一个异常
try的工作原理是,当开始一个try语句后,python就在当前程序上下文中作标记,这样当出现异常时,就可以返回这里,try子句先执行,接下来会发生什么依赖于执行时是否会出现异常; 当try语句执行时发生异常,python就跳回到try并执行第一个匹配该异常的except子句,异常处理完成后,控制流就通过整个try语句(除非再处理异常时又出现新的异常); 如果try后的语句发生了异常,却没有匹配到except子句,异常将被递交到上层的try,或者程序最上层,这样将结束程序,并打印出缺省的出错信息。

执行完主函数的一条任务后,python会在第一时间返回到try中,
对于下边的程序:
(1) python控制流到def gen():发现定义了个函数,跳到主函数if name == ‘main‘:
(2)流程到主函数这里,进行下一步g = gen()发现是个生成器,进行下一步
(3)需要打印生成器的第一个元素,需要返回定义的函数,生成器
(4)返回生成器后遇到while 1:,为真执行循环:读取try命令,遇到yield ‘a’,做标记,并输出a,返回主函数的第二条打印命令
(5)输出同样是需要返回生成器,返回定义的生成器,在上一次标记位置yield ‘a’,跳到try的yield ‘a’的下条命令:yield ‘b’,并输出“b“
(6)打印完成后,进行下一步:此时g.throw(TypeError)给生成器抛了一个TypeError异常,返回生成器上次标记位:yield ‘b’:进行异常处理:except比对匹配异常,并处理,打印出’测试throw方法’,异常处理完成后,这时python控制权交给try,并标记yield ‘a’这里;接着控制流读取主函数的下一条命令,就是第三条打印命令发现需要返回生成器:返回生成器从标记处yield ‘a’读取下一条命令yield ‘b’会打印出b
(7)打印完成后读取主函数第四条打印命令,同样需要返回生成器;此时去try那里,重新标记,到yield ‘a’生成a,打印出a
(8)完成后执行第5条打印命令,继续返回生成器,由于上次控制流驻留在yield ‘a’处,所以第5条命令会打印出b
(9)完成后,主函数遇到g.throw(ValueError)异常:返回生产器,except逐一匹配异常,并做处理,打印出Value Error,之后控制流重新到try,并在yield ‘a’处标记驻留,
(10)返回主函数执行第六条打印任务,同样需要返回生成器,上次驻留在yield ‘a’处,所以第5条打印任务会打印出b
(11)第7条打印任务,返回生成器时,上次留在yield ‘b’处,所以这次会从头生成a,同样停在a处

def gen():
    while 1:
        try:
            yield 'a'
            yield 'b'
        except TypeError:
            print '测试throw方法'
        except ValueError:
            print 'Value Error'
if __name__ == '__main__':
    g = gen()
    print g.next()
    print next(g)
    g.throw(TypeError)
    print g.next()
    print g.next()
    print g.next()
    g.throw(ValueError)
    print g.next()
    print g.next()

执行结果

a
b
测试throw方法
b
a
b
Value Error
b
a
*.send()方法,用于给生成器发送某一信息,
def res():
    while 1:
        receive = yield ' '
        if receive == 'a':
            print "收到a"
        elif receive == 'b':
            print '收到b'
        else:
            print '不清楚大哥你发的什么?'
g=res()
next(g)
info =raw_input('info:')
g.send(info)

运行一下:

info:qww
不清楚大哥你发的什么?
实验:
def chat_robot():
    res = ''
    while True:
         receive = yield res
         if '你好' in receive  or 'hi' in receive:
             res =  '你好,我是机器人小冰!'
         elif "年龄" in receive:
             res = '小冰1岁了!'
         elif 'name' in receive or '名字' in receive:
             res = '你的名字呢?'
         else:
             res = '小冰不知道你在说什么?正在学习中......'

Chat = chat_robot()
Chat.next()

while True:
    send_info = raw_input('>>A:').strip()
    if send_info == 'bye':
        print '机器人不和你玩了!'
        break

    response = Chat.send(send_info)
    print '小冰>>:%s' %(response)

Chat.close

这里写图片描述
实验效果:

这里写图片描述

四.生成器_无缓冲区的生产消费者模型

import time
import random
def  consumer(name):
    print '[%s]准备买粉条...' % name
    while True:
        kind = yield
        print '客户[%s]购买了[%s]口味的粉条...' %(name ,kind)

def producer(pname):
    c1 = consumer('WANG')
    c2 = consumer('Leo')

    c1.next()
    next(c2)
    print '厨师[%s]准备制作粉条。。。' %(pname)
    for kind in ['三鲜','麻辣','特辣']:
        time.sleep(random.random()*5)
        print '[%s]制作了[%s]口味的粉条...' %(pname,kind)
        c1.send(kind)
        c2.send(kind)
    c1.close()
    c2.close()
producer('TOM')

运行结果:

[WANG]准备买粉条...
[Leo]准备买粉条...
厨师[TOM]准备制作粉条。。。
[TOM]制作了[三鲜]口味的粉条...
客户[WANG]购买了[三鲜]口味的粉条...
客户[Leo]购买了[三鲜]口味的粉条...
[TOM]制作了[麻辣]口味的粉条...
客户[WANG]购买了[麻辣]口味的粉条...
客户[Leo]购买了[麻辣]口味的粉条...
[TOM]制作了[特辣]口味的粉条...
客户[WANG]购买了[特辣]口味的粉条...
客户[Leo]购买了[特辣]口味的粉条...

五.生成器_有缓冲区的生产消费者模型


import time
import random
cache =[]
def consumer(name):
print ‘[%s]准备买粉条…’ % name
while True:
kind = yield
cache.remove(kind)
print ‘客户[%s]购买了[%s]口味的粉条…’ %(name ,kind)

def producer(pname):

print '厨师[%s]准备制作粉条。。。' %(pname)
for kind in ['三鲜','麻辣','特辣']:
    time.sleep(random.random()*5)
    print '[%s]制作了[%s]口味的粉条...' %(pname,kind)
    cache.append(kind)

producer(“TOM”)
c1 = consumer(‘WANG’)
c1.next()
c1.send(‘三鲜’)

print ‘本店现有粉条口味: ’ ,
for i in cache:
print i,

运行结果

厨师[TOM]准备制作粉条。。。
[TOM]制作了[三鲜]口味的粉条...
[TOM]制作了[麻辣]口味的粉条...
[TOM]制作了[特辣]口味的粉条...
[WANG]准备买粉条...
客户[WANG]购买了[三鲜]口味的粉条...
本店现有粉条口味:  麻辣 特辣

生成器的优势总结:

  1. 生成器提供了一种更为便利的产生迭代器的方式, 一般用户不需要自己实现iter和next方法,它默认返回一个可迭代对象;
  2. 代码更为简洁,优雅;
  3. 节省存储空间
  • 9
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值