Python之三元表达式、迭代器、生成器---第十一天

1、定义

(1)迭代器协议:对象必须提供一个next()方法,执行该方法要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代
(2)可迭代对象:实现了迭代器协议的对象(如何实现?对象内部定义了一个_iter_()方法)
(3)协议是一种约定,可迭代对象实现了迭代器协议,python的内部工具(如for循环、sum、min、max函数等)使用迭代器协议访问对象

2、for循环的本质

循环所有对象,全都是使用迭代器协议

3、疑点
for循环的本质是遵循迭代器协议去访问对象,那么for循环的对象肯定都是迭代器了啊,那for循环可以遍历字符串、列表、、字典、集合文件对象,那么这些类型的数据肯定都是可迭代对象吗?但是,列表中没有next()方法,为什么?

解答:以上for循环遍历那些不是可迭代对象,只不过在for循环式,调用了他们内部的_iter_方法,把他们变成了可迭代对象
然后for循环调用可迭代对象的_next_()方法,捕捉Stoplteration异常,以终止迭代,有个自带的内置方法,next()方法,是一样的。

4、三元表达式

(1)表达式结构:if成立的返回值 + if判断 + else if不成立的返回值
(2)注意:元就是运算符的意思,可以小于等于三元,不能超过三元

5、生成器
(1)什么是生成器?
可以理解为一种数据类型,这种数据类型自动实现了迭代器协议(其他的数据类型需要调用自己内置的_iter_方法),所以生成器是可迭代对象
(2)生成器在python中的表现形式

  • 生成器函数:常规定义函数,使用的是yeild语句返回而不是return返回,yeild语句每次返回一个结果,在每个结果中间,挂起函数的状态,以便下次从它离开的地方继续执行
  • 生成器表达式:类似于列表推导,但是,生成器但会按需生产的一个对象,而不是一次构建一个结果列表
    (3)生成器特点:
  • 是可迭代对象
  • 实现了延迟计算,一次返回一个结果,提高代码可读性
  • 代码简洁,占空间小,节省内存地址
  • 生成器本质和其他的数据类型一样,都是实现了迭代器协议,只不过生成器附加了一个延迟计算内存的好处,其余的可迭代对象没有这点好处
  • 生成器只能遍历一次
  • 可以保留函数状态
  • 效率高(回想老母鸡下蛋实例,下一个卖一个)

6、列表解析
列表解析使代码更简洁,举例如下:
(1)不用列表解析的代码:

l=[]
for i in range(10):
  l.append("鸡蛋%s"%i)
print(l)

#输出结果:
['鸡蛋0', '鸡蛋1', '鸡蛋2', '鸡蛋3', '鸡蛋4', '鸡蛋5', '鸡蛋6', '鸡蛋7', '鸡蛋8', '鸡蛋9']

(2)用列表解析的代码:

l=["鸡蛋%s"%i for i in range(10)]
print(l)

#输出结果:同上

(3)还可以加判断:

l=["鸡蛋%s"%i for i in range(10) if i > 5]
print(l)

#输出结果:
['鸡蛋6', '鸡蛋7', '鸡蛋8', '鸡蛋9']

(4)没有四元表达式,不可以放太多

l=["鸡蛋%s"%i for i in range(10) if i > 5 else i]
print(l)

#说明:else i 是错误的

(5)把列表解析的[]换成()得到的就是生成器表达式

7、生产者消费者模型实例—输送4个包子,现做现吃

import time

def consumer(name):
    print("我是【%s】,我要开始吃包子了"%name)
    while True:
        baozi=yield
        time.sleep(1)
        print("【%s】很开心的把【%s】吃掉了"%(name,baozi))
def producer():
    c1=consumer("Test1")
    c2=consumer("Test2")
    c1.__next__()
    c2.__next__()
    for i in range(4):
        time.sleep(1)
        c1.send("包子%s"%i)
        c2.send("包子%s"%i)
producer()


#输出结果:
我是【Test1】,我要开始吃包子了
我是【Test2】,我要开始吃包子了
【Test1】很开心的把【包子0】吃掉了
【Test2】很开心的把【包子0】吃掉了
【Test1】很开心的把【包子1】吃掉了
【Test2】很开心的把【包子1】吃掉了
【Test1】很开心的把【包子2】吃掉了
【Test2】很开心的把【包子2】吃掉了
【Test1】很开心的把【包子3】吃掉了
【Test2】很开心的把【包子3】吃掉了

注意
(1)触发生成器运行的第三种情况send(None)。
(2)当yeild被赋值的时候,send的参数就是yeild的返回值,每次执行以yeild结束。

作业解读:
(1)所有能用递归解决的问题都可以用for循环来解决
(2)break、contine、 return区别

  • break结束当前循环
  • continue结束本次循环进入下一循环
  • return结束函数,并返回结果,默认为None
    (3)Python 3 中的range函数和Python 2.7中的range函数有什么区别?
  • 3.x range不会生成值,只有用的时候才会生成
  • 2.7 range会生成一个列表,值已经生成
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章