wns9778.com_威尼斯wns.9778官网

热门关键词: wns9778.com,威尼斯wns.9778官网
wns9778.com > 计算机教程 > day11-12-迭代器和生成器

原标题:day11-12-迭代器和生成器

浏览次数:150 时间:2019-05-10

python_day_13

迭代器

今日主要内容

  1.函数名的运用

      函数名是一个特殊的变量,与括号搭配可以调用函数

      1.函数名的内存地址

      图片 1

      2.函数名可以赋值给其他变量

      图片 2

      3.函数名可以当做容器类的元素

      图片 3

      4.函数名可以当做函数的参数

      图片 4

      5.函数名可以作为函数的返回值

      图片 5

  1. 生成器和生成器函数
    生成器的本质就是迭代器
    生成器的三种创建办法:

  2.闭包

    闭包:内层函数对外层函数变量的引用

    

1 def func1():    2 name = "alex"    3     def func2():        4         print     # 闭包    5     func2() 6 func1() 7 结果: alex    

    我们可以使用__closure__来检测函数是否是闭包. 使⽤用函数名.__closure__返回cell就是闭包. 返回None就不是闭包.
    在函数外边调用内部函数,只需使用return返回即可。

     闭包的好处:使用闭包,可以保证外层函数的变量在内存中常驻,供后面的程序使用。

  • 1.通过生成器函数
  • 2.通过生成器表达式创建生成器
  • 3.通过数据转换

    生成器函数:
    函数中包含了yield的就是生成器函数
    注意:生成器函数被执行. 获取到的是生成器. 而不是函数的执行
    生成器表达式:
    (结果 for 变量 in 可迭代对象 if 筛选)
    取值:

    1. __next__()
    1. send(值) 给上一个yield位置传一个值, 第一个和最后一个yield不用传值
    1. 可以for循环
    1. list(g)
    1. 各种推导式和生成器表达式
    1. 列表推导式 [结果 for 变量 in 可迭代对象 if 筛选]
    1. 字典推导式 {结果 for 变量 in 可迭代对象 if 筛选} 结果=>key:value
    1. 集合推导式 {结果 for 变量 in 可迭代对象 if 筛选} 结果=>key

  3.迭代器

    查看是否为可迭代对象,第一种办法,使用dir判断是否有__iter__()。

    图片 6

      如果对象中有__iter__函数. 那么我们认为这个对象遵守了可迭代协议. 就可以获取到相应的迭代器. 这⾥的__iter__是帮助我们获取到对象的迭代器. 我们使⽤迭代 器中的__next__()来获取到⼀一个迭代器中的元素.

      图片 7

      使用while循环 迭代器来模拟for循环

      图片 8

      总结:

      lterable:可迭代对象,内部包含__iter__()含糊

      lterator:迭代器。内部包含__iter()__同时包含__next__()

      迭代器的特点:

        1.节省内存

        2.惰性机制

        3.不能反复,只能向下执行

      我们可以把迭代的内容想象成子弹,获取到迭代器__iter__().当成把子弹装到弹夹中。然后发射就是__next__()把每一个子弹打出来。也就是说, for循环的时候. ⼀开始的 时候是__iter__()来获取迭代器. 后⾯每次获取元素都是通过__next__()来完成的. 当程序遇到 StopIteration将结束循环.

12. 前⽅⾼能-⽣成器和⽣成器表达式

生成器和表达式

本节主要内容:

  1.生成器

      生成器实质就是迭代器。

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

      1.通过生成器函数

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

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

      图片 9

      图片 10

      如果函数中存在了yield,那么这个函数就是个生成器函数。这个时候,我们在执行这个函数,就是在获取这个生成器了。

      图片 11

      注意:当程序运行完最后一个yield后,那么后面继续进行__next__()程序则会报错。

      send方法, send和__next__()一样都可以让生成器执⾏到下⼀个yield。     

      send和__next__()区别:

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

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

      生成器可以用for循环来获取内部元素。

      图片 12

    1. ⽣成器和⽣成器函数
    1. 列表推导式

  2.列表推导式,生成器表达式以及其他推导式

      列表推导式:通过一行来构建你要的列表,

lst = [i for i in range]

      还可以对数据进行筛选:

      图片 13

      生成器表达式跟列表推导式的语法基本一样,只是[ ]换成()

      图片 14

      生成器表达式和列表推导式的区别:

        1.列表推导式比较耗内存,一次性加载。生成器表达式基本上不占内存,使用的时候分配和使用内存

        2.得到的值不一样,列表推导式得到了一个列表,生成器表达式得到了一个生成器。

        注意:生成器的惰性机制,只有在访问的时候取值。

        图片 15

      字典推导式:

图片 16

      集合推导式:生成一个集合。

      总结: 推导式有, 列表推导式, 字典推导式, 集合推导式, 没有元组推导式

        ⽣成器表达式: (结果 for 变量量 in 可迭代对象 if 条件筛选)

        生成器表达式可以直接获取到生成器对象. 生成器对象可以直接进行for循环. ⽣成器具有惰性机制.

⼀. ⽣成器 什么是⽣成器. ⽣成器实质就是迭代器.

在python中有三种⽅式来获取⽣成器:

    1. 通过⽣成器函数
    1. 通过各种推导式来实现⽣成器
    1. 通过数据的转换也可以获取⽣成器

⾸先, 我们先看⼀个很简单的函数:

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 0x00000276E516DF68>

运⾏的结果和上⾯不⼀样. 为什么呢. 由于函数中存在了yield. 那么这个函数就是⼀个⽣成器 函数. 这个时候. 我们再执⾏这个函数的时候. 就不再是函数的执⾏了. ⽽是获取这个⽣成器. 如何使⽤呢? 想想迭代器. ⽣成器的本质是迭代器.

所以. 我们可以直接执⾏__next__()来执⾏ 以下⽣成器.

def func():
    print("111")
    yield 222

gener = func()# 这个时候函数不会执⾏. ⽽是获取到⽣成器
ret = gener.__next__()# 这个时候函数才会执⾏. yield的作⽤和return⼀样. 也是返回数据
print(ret)
结果:
111
222

那么我们可以看到, yield和return的效果是⼀样的. 有什么区别呢? yield是分段来执⾏⼀个 函数. return呢? 直接停⽌执⾏函数.

def func():
    print("111")
    yield 222
    print('333')
    yield 444

gener = func()
ret = gener.__next__()
print(ret)
ret2 = gener.__next__()
print(ret2)
ret3 = gener.__next__()
print(ret3)# 最后⼀个yield执⾏完毕. 再次__next__()程序报错, 也就是说. 和return⽆关了.

结果:
111
Traceback (most recent call last):
222
  File "D:/pycodes/第13天/day13.py", line 117, in <module>
333
    ret3 = gener.__next__() # 最后⼀个yield执⾏完毕. 再次__next__()程序报错, 也就是说. 和return⽆关了.
444
StopIteration

当程序运⾏完最后⼀个yield. 那么后⾯继续进⾏__next__()程序会报错. 好了⽣成器说完了.

⽣成器有什么作⽤呢? 我们来看这样⼀个需求. 老男孩向JACK JONES订 购10000套学⽣服. JACK JONES就比较实在. 直接造出来10000套衣服.

def cloth():
    lst = []
    for i in range(0,10000):
        lst.append('衣服' str(i))
    return lst
cl = cloth()

但是呢, 问题来了. 老男孩现在没有这么多学⽣啊. ⼀次性给我这么多. 我往哪⾥放啊. 很尴尬 啊. 最好的效果是什么样呢? 我要1套. 你给我1套. ⼀共10000套. 是不是最完美的.

def cloth():
    for i in range(0, 10000):
        yield "⾐服" str(i)
cl = cloth()
print(cl.__next__())
print(cl.__next__())
print(cl.__next__())
print(cl.__next__())

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

接下来我们来看send⽅法, send和__next__()⼀样都可以让⽣成器执⾏到下⼀个yield.

def eat():
    print("我吃什么啊")
    a = yield "馒头"
    print("a=",a)
    b = yield "⼤饼"
    print("b=",b)
    c = yield "⾲菜盒⼦"
    print("c=",c)
    yield "GAME OVER"
gen = eat() # 获取⽣成器
ret1 = gen.__next__()
print(ret1)
ret2 = gen.send("胡辣汤")
print(ret2)
ret3 = gen.send("狗粮")
print(ret3)
ret4 = gen.send("猫粮")
print(ret4)

send和__next__()区别:

  1. send和next()都是让⽣成器向下走⼀次
  1. send可以给上⼀个yield的位置传递值, 不能给最后⼀个yield发送值. 在第⼀次执⾏⽣ 成器代码的时候不能使⽤send()

⽣成器可以使⽤for循环来循环获取内部的元素:

def func():
    print(111)
    yield 222
    print(333)
    yield 444
    print(555)
    yield 666
gen = func()
for i in gen:
    print(i)
结果:
111
222
333
444
555
666

⼆. 列表推导式, ⽣成器表达式以及其他推导式 ⾸先我们先看⼀下这样的代码, 给出⼀个列表, 通过循环, 向列表中添加1-13 :

lst = []
for i in range(1, 15):
    lst.append(i)
print(lst)

替换成列表推导式:

lst = [i for i in range(1, 15)]
print(lst)

列表推导式是通过⼀⾏来构建你要的列表, 列表推导式看起来代码简单. 但是出现错误之 后很难排查.

列表推导式的常⽤写法: [ 结果 for 变量 in 可迭代对象]

本文由wns9778.com发布于计算机教程,转载请注明出处:day11-12-迭代器和生成器

关键词: wns9778.com

上一篇:vue2.x 给一个对象里添加一个没有的属性

下一篇:没有了