• Day12 Python基础之生成器、迭代器(高级函数)(十)


     https://www.cnblogs.com/yuanchenqi/articles/5769491.html

    1. 列表生成式

    我现在有个需求,看列表[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],我要求你把列表里的每个值加三次方,你怎么实现?你可能会想到2种方式

    1 a=[0,1,2,3,4,5,6,7,8,9]
    2 b=[]
    3 for i in a:
    4     b.append(i+1)
    5 a=b
    6 print(a)
    普通版本
     1 a=map(lambda x:x+1,range(10))
     2 print(a,type(a))
     3 for i in a:
     4     print(i)
     5 
     6 输出结果:
     7 <map object at 0x0272A4D0> <class 'map'>
     8 1
     9 2
    10 3
    11 4
    12 5
    13 6
    14 7
    15 8
    16 9
    17 10
    文艺版本
     1 (1 2 t=[0,1]
     3 a,b=t
     4 print(a)
     5 print(b)
     6 输出结果:
     7 0
     8 1
     9 (210 t=[0,1,2]
    11 a,b=t
    12 print(a)
    13 print(b)
    14 输出结果:
    15 ValueError: too many values to unpack (expected 2)
    16 (317 t=[0,1]
    18 a,b,cc=t
    19 print(a)
    20 print(b)
    21 print(c)
    22 输出结果:
    23 ValueError: not enough values to unpack (expected 3, got 2)
    小知识点 
     1 def f(n):
     2     return n**3
     3 a=[f(x) for x in range(10)]
     4 print(a,type(a))
     5 
     6 等价于
     7 a=[x**3 for x in range(10)]
     8 print(a,type(a))
     9 输出结果:
    10 [0, 1, 8, 27, 64, 125, 216, 343, 512, 729] <class 'list'>
    装逼版本

    2. 生成器(generator)

    生成器的创建方式有两种:()和yield

     1 a=(x**3  for x in range(10))
     2 print(a,type(a))
     3 
     4 等价于
     5 def f(n):
     6     return n**3
     7 a=(f(x) for x in range(10))
     8 print(a,type(a))
     9 
    10 输出结果:
    11 <generator object <genexpr> at 0x02DC34B0> <class 'generator'>
    简单生成器之()生成演示

    生成器数据类型的变量指向的内存地址,根本就没有任何数据在内存中,也没有存储在任何地方。

    (类比理解:列表是将数据存储在变量指向的内存空间的,这就相当于你冰箱里面放了十道菜,你想吃哪个就去拿,这是占用一定的空间的,为了解决这个问题,我们有了生成器,就好比你拥有了一个有脾气的厨师,让厨师给你现做现吃,做哪个你就吃哪个好了,在生成器s中可以用生成器内置方法s.__next__()或者python内置函数next(s)这个方法按顺序生成值,这取决于你生成器的本身的特性。建议使用next(s)

    生成生成器对象里面的值

     1 a=(x*2 for x in range(10))
     2 print(a,type(a))
     3 print(a.__next__())
     4 print(next(a))
     5 print(next(a))
     6 print(next(a))
     7 输出结果:
     8 <generator object <genexpr> at 0x028B34B0> <class 'generator'>
     9 0
    10 2
    11 4
    12 6
    next()生成值

     注:生成器就是一个可迭代对象,迭代器也是可迭代对象

     1 a=(x*2 for x in range(4))
     2 print(a,type(a))
     3 
     4 for i in a:
     5     print(i)
     6 
     7 输出结果:
     8 0
     9 2
    10 4
    11 6
    遍历生成器

    注:(1)for循环可遍历可迭代对象,有__iter__方法的都是可迭代对象内部的方法,iter()是内置函数

    (2)for循环遍历可迭代对象的三个步骤:

        • 调用可迭代对象的iter方法,返回一个迭代器对象
        • 不断调用迭代器的next方法
        • 处理stopiteration异常

    while:

    try:

    i=next(generator) 

    except StopIteration

    break 

    (3)当内存中的数据,没有变量引用的时候(即没有变量指向该内存地址),该数据就会被python的解释器当垃圾清除掉

     这样就算遍历生成器,也不会占用大量内存,因为i的指向一直在更新,没有被引用的数据就会被清除

    1 def f():
    2     print('Hello')
    3     yield  1
    4     print('Ok')
    5     yield  2
    6 g=f()
    7 print(g,type(g))
    8 输出结果:
    9 <generator object f at 0x033634B0> <class 'generator'>
    简单生成器之yield生成演示

    注:没有yield就是普通的函数,有yeild,定义的函数f()就是一个生成器对象,有几个yield就相当于几道菜。

    生成生成器对象里面的值

     1 def f():
     2     print('Hello')
     3     yield  1
     4     print('Ok')
     5     yield  2
     6 g=f()
     7 next(g)
     8 next(g)
     9 输出结果:
    10 Hello
    11 Ok
    next()

    注:

    (1)每调用一次next(g),就执行一遍g函数,以yield为结束点,返回1(相当于return结束函数的运行),再执行一遍next(g),以上次的结束点为起点,继续执行g函数,并返回2

    (2)可通过yield实现在单线程的情况下实现并发运算的效果,即伪并发,CPU切换速度特别快,以至于我们不觉得有切换这一过程

     1 def f():
     2     print('Hello')
     3     yield  1
     4     print('Ok')
     5     yield  2
     6 g=f()
     7 
     8 for i in g:
     9     print(i)
    10 输出结果:
    11 Hello
    12 1
    13 Ok
    14 2
    for循环遍历生成对象

    注:for循环遍历生成对象g,以yield结束标志执行函数内容,并打印出了yield返回值

     1 def fibo(N):
     2     Max=N
     3     n,before,after=0,0,1
     4     while n<Max:
     5         # print(after)
     6         yield after
     7         before,after=after,before+after
     8         n+=1
     9 g=fibo(8)
    10 # print(next(g))
    11 # print(next(g))
    12 # print(next(g))
    13 for i in g:
    14     print(i)
    yield生成斐波那契数列 

     生成器对象的send方法 

     1 def fibo(N):
     2     Max=N
     3     n,before,after=0,0,1
     4     while n<Max:
     5         # print(after)
     6         count=yield after
     7         print(count)
     8         before,after=after,before+after
     9         n+=1
    10 g=fibo(8)
    11 
    12 g.send(None)    #相当于next(g),先进入生成器对象,遇到yield,返回after后结束
    13 g.send('eee')   #从上一次结束点开始,继续程序,将send的参数赋值给count,继续执行后面的语句,直到再次遇到yield
    14 输出结果:
    15 eee
    send方法传参数

    注:进入生成器后(next,send(None))再能send传参数

    3. 迭代器(iterator)

    生成器都是迭代器,迭代器不一定是生成器;

    可迭代对象(Iterable)不一定是迭代器(Iterator),通过iter方法可以把可迭代对象变成迭代器(迭代器对象),这是因为可迭代对象里面有__iter__方法。

    什么是迭代器:需要满足两个条件:(1)有iter方法(2)有next方法

     1 from collections import Iterable,Iterator
     2 d=[1,2,3,4,5,6]
     3 a=iter(d)
     4 print(a,type(a))
     5 # print(next(a))
     6 # # print(next(a))
     7 # for i in a:
     8 #     print(i)
     9 print(isinstance(d,Iterable))    #判断d是不是可迭代对象
    10 print(isinstance(d,list))    #判断d是不是列表
    11 print(isinstance(d,Iterate))    #判断的是不是迭代器
    迭代器

     

     

     

     

     

     

  • 相关阅读:
    java JSONObject
    android 8.0 悬浮窗 最简demo
    使用adb 命令(atrace)抓起systrace的方法。
    使用python处理selenium中的获取元素属性
    使用adb/Linux获取网关ip
    Requests text乱码
    python-uiautomator2
    adb命令 判断锁屏
    缓存穿透、缓存击穿与缓存雪崩
    ReentrantLock重入锁详解
  • 原文地址:https://www.cnblogs.com/weinapang/p/9168388.html
Copyright © 2020-2023  润新知