【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方法

 

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

posted @ 2019-05-04 13:02  Rollo|St  阅读(163)  评论(0编辑  收藏  举报