zoukankan      html  css  js  c++  java
  • 【Rollo的Python之路】Python 生成器

    Python 列表生成式:

    x从range里面取元素,然后对x进行运算,生成列表

    list1 = [x for x in range(10)]  #列表生成式
    
    print(list1)
    
    
    #执行结果:
    
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

    或者可以这样:

    list1 = [x**2 for x in range(10)]  #列表生成式
    
    print(list1)
    
    #执行结果:
    
    [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

    运算符可以是函数:

    def f(x):
        return x**3
    
    list1 = [f(x) for x in range(10)]  #列表生成式
    
    print(list1)
    
    #执行结果:
    
    [0, 1, 8, 27, 64, 125, 216, 343, 512, 729]
    def f(x):
        return x**3
    
    list1 = [f(x) for x in range(10)]  #列表生成式
    
    print(list1)
    print(type(list1))
    
    #执行结果:
    
    [0, 1, 8, 27, 64, 125, 216, 343, 512, 729]
    <class 'list'>

    另一种赋值形式:要求一一对应,不然就报错。

    t = (123,"abc")
    
    a,b = t
    print(a)
    print(b)
    
    #执行结果:
    
    123
    abc
    t = [123,"abc",891]  #可以是列表
    
    a,b,c = t
    print(a)
    print(b)
    print(c)
    
    #执行结果:
    
    123
    abc
    891

    Python 生成器:一边循环,一边计算的机制,叫作生成器

    内存的效率

    生成器就是一个可迭代对象!!!

    生成器创建方式:

    1.0 小括号的方式(s = (x*2 for x in range(10)))

    2.0 yield创建

    s = (x*2 for x in range(10))
    print(s)
    
    #执行结果:
    
    <generator object <genexpr> at 0x0000000001EB6138>

    调用方法:next()

    s = (x*2 for x in range(10))
    
    print(next(s))
    print(next(s))
    print(next(s))
    print(next(s))
    
    #执行结果:
    
    0
    2
    4
    6

    相当于:__next__()

    s = (x*2 for x in range(10))
    
    print(s.__next__())
    print(s.__next__())
    print(s.__next__())
    print(s.__next__())
    
    #执行结果:
    
    0
    2
    4
    6

    超出了就会报错:StopIteration

    用for循环来遍历一次:

    s = (x*2 for x in range(10))
    
    for i in s:
        print(i)
    
    #执行结果:
    
    0
    2
    4
    6
    8
    10
    12
    14
    16
    18

     生成器函数:

    def generator_function():
        yield 
        

    在一个一般函数中使用yield关键字,可以实现一个最简单的生成器,此时这个函数变成一个生成器函数。yield与return返回相同的值,区别在于return返回后,函数状态终止,而yield会保存当前函数的执行状态,在返回后,函数又回到之前保存的状态继续执行。

    看看yield与return的区别:

    def generator_function1():
        print("ok")
        return 100 
    
    generator_function1()
    
    def generator_function():
        print("ok")
        yield 100
    generator_function()
    #执行结果: 
    ok
    def generator_function():
        print("ok")
        yield 100
    
    t = generator_function()
    print(t)
    
    #执行结果:
    <generator object generator_function at 0x00000000021F6138>

    所以yield函数就是一个生成器对象。

    def generator_function():
        print("ok")
        yield 100
        print("ok22")
        yield 99
    
    t = generator_function()
    print(t)
    
    next(t) #保留在yield 100
    next(t) #第二次从yied 100以下开始走。不是从开头走
    
    #执行结果:
    <generator object generator_function at 0x0000000002216138>
    ok
    ok22

     也可以用for:

    def generator_function():
        print("ok")
        yield 100
        print("ok22")
        yield 99
    
    for i in generator_function():
        print(i)
    
    
    #执行结果:
    
    ok
    100
    ok22
    99

    斐波那契数列

    def fibo(max):
        n,before,after = 0,0,1
       print(n) while n < max: print(after) before,after = after, before + after n = n + 1 fibo(10) #执行结果: 0 1 1 2 3 5 8 13 21 34 55

     用生成器来改:

    def fibo(max):
        n,before,after = 0,0,1
    
        while n < max:
            # print(after)
            yield before
            before,after = after, before + after
            n = n + 1
    
    g = fibo(8)
    print(g)
    
    print(next(g))
    
    #执行结果
    <generator object fibo at 0x0000000002216138>
    0

    yield()还有一个send()方法:

    send():可以传值,第一次进函数只能传None,等同于next(b)

    def battle():
        print("battle one")
        count = yield 1
        print(count)
    
        print("battle two")
        yield 2
        print("battle three")
        yield 3
    
    b = battle()
    b.send(None) #可以传值,第一次进函数只能传None,等同于next(b)
    b.send(99)

    for 循环语句,深入理解:

      1.0 for循环后面加的是可迭代对象。

          可迭代对象:内部有用iter()方法的对象都是可迭代对象。列表,元组,字典都是可迭代对象

      2.0 内部调用了next方法。

         

    生成器函数包含一个或者多个yield当调用生成器函数时,函数将返回一个对象,但是不会立刻向下执行像__iter__()和__next__()方法等是自动实现的,所以我们可以通过next()方法对对象进行迭代一旦函数被yield,函数会暂停,控制权返回调用者局部变量和它们的状态会被保存,直到下一次调用函数终止的时候,StopIteraion会被自动抛出生成器如何节省资源?

    只记住当前位置,生成器只保留一个值,next之后上一个值就没有了

    只有一个next方法

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

  • 相关阅读:
    STL map用法总结(multimap)
    Ice Cream Tower
    位运算 进制转化 STL中bitset用法
    《算法导论》插入排序
    C++输入/输出流
    kuangbin大佬模板(侵删)- hdu 2222
    poj 3461
    动态规划入门-01背包问题
    Dropping water balloons (入门dp)
    TSP
  • 原文地址:https://www.cnblogs.com/rollost/p/10808209.html
Copyright © 2011-2022 走看看