生成器

通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包行100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,到后面绝大多数元素占用的空间都白白浪费了。

所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节约大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器: generator。

要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator;

#!/usr/bin/env python3.8
# __author: "smoke"
# date: 2021/1/15 下午9:59

s = (x * 2 for x in range(10))

print(s)

/home/smoke/PycharmProjects/pythonProject/venv/bin/python /home/smoke/PycharmProjects/pythonProject/lean_python/generator.py
<generator object <genexpr> at 0x7fc84ad9c970>    #生成器对象,不占用内存

Process finished with exit code 0

#!/usr/bin/env python3.8
# __author: "smoke"
# date: 2021/1/15 下午9:59

s = [x * 2 for x in range(1000000000000)]    #生成器,占用内存空间

print(s)

#!/usr/bin/env python3.8
# __author: "smoke"
# date: 2021/1/15 下午9:59

s = (x * 2 for x in range(1000000000000))
print(s)

print(s.__next__())    #调用生成器对象,特殊内部方法不建议使用

/home/smoke/PycharmProjects/pythonProject/venv/bin/python /home/smoke/PycharmProjects/pythonProject/lean_python/generator.py
<generator object <genexpr> at 0x7f86e72c0970>
0

Process finished with exit code 0

#!/usr/bin/env python3.8
# __author: "smoke"
# date: 2021/1/15 下午9:59

s = (x * 2 for x in range(1000000000000))
print(s)

print(next(s))    #建议使用这种方法,等价于s.__next__() in Py2:s.next()

/home/smoke/PycharmProjects/pythonProject/venv/bin/python /home/smoke/PycharmProjects/pythonProject/lean_python/generator.py
<generator object <genexpr> at 0x7fe3f3340970>
0

Process finished with exit code 0

#!/usr/bin/env python3.8
# __author: "smoke"
# date: 2021/1/15 下午9:59

s = (x * 2 for x in range(1000000000000))
print(s)

print(next(s))
print(next(s))    #只能按顺序

/home/smoke/PycharmProjects/pythonProject/venv/bin/python /home/smoke/PycharmProjects/pythonProject/lean_python/generator.py
<generator object <genexpr> at 0x7fd034856970>
0
2

Process finished with exit code 0

#!/usr/bin/env python3.8
# __author: "smoke"
# date: 2021/1/15 下午9:59

s = (x * 2 for x in range(5))
print(s)

print(next(s))
print(next(s))
print(next(s))
print(next(s))
print(next(s))

/home/smoke/PycharmProjects/pythonProject/venv/bin/python /home/smoke/PycharmProjects/pythonProject/lean_python/generator.py
<generator object <genexpr> at 0x7f5978e08970>
0
2
4
6
8

Process finished with exit code 0

#!/usr/bin/env python3.8
# __author: "smoke"
# date: 2021/1/15 下午9:59

s = (x * 2 for x in range(5))
print(s)

print(next(s))
print(next(s))
print(next(s))
print(next(s))
print(next(s))
print(next(s))

/home/smoke/PycharmProjects/pythonProject/venv/bin/python /home/smoke/PycharmProjects/pythonProject/lean_python/generator.py
<generator object <genexpr> at 0x7fcc39039970>
0
2
4
6
8
Traceback (most recent call last):
  File "/home/smoke/PycharmProjects/pythonProject/lean_python/generator.py", line 13, in <module>
    print(next(s))
StopIteration

Process finished with exit code 1

#!/usr/bin/env python3.8
# __author: "smoke"
# date: 2021/1/15 下午9:59

s = (x * 2 for x in range(10))
print(s)

for i in s:    #生成器就是一个可迭代对象(Iterable)
    print(i)

/home/smoke/PycharmProjects/pythonProject/venv/bin/python /home/smoke/PycharmProjects/pythonProject/lean_python/generator.py
<generator object <genexpr> at 0x7f83455e2970>
0
2
4
6
8
10
12
14
16
18

Process finished with exit code 0

生成器一共两种创建方式:

1. (x*2 for x in range(5))

2. yield

#!/usr/bin/env python3.8
# __author: "smoke"
# date: 2021/1/15 下午9:59

def foo():
    return 1

foo()

/home/smoke/PycharmProjects/pythonProject/venv/bin/python /home/smoke/PycharmProjects/pythonProject/lean_python/generator.py

Process finished with exit code 0

#!/usr/bin/env python3.8
# __author: "smoke"
# date: 2021/1/15 下午9:59

def foo():
    yield 1    #生成器

print(foo)

/home/smoke/PycharmProjects/pythonProject/venv/bin/python /home/smoke/PycharmProjects/pythonProject/lean_python/generator.py
<function foo at 0x7f8258ade280>

Process finished with exit code 0

#!/usr/bin/env python3.8
# __author: "smoke"
# date: 2021/1/15 下午9:59

def foo():
    print('ok')
    yield 1

foo()

/home/smoke/PycharmProjects/pythonProject/venv/bin/python /home/smoke/PycharmProjects/pythonProject/lean_python/generator.py

Process finished with exit code 0

#!/usr/bin/env python3.8
# __author: "smoke"
# date: 2021/1/15 下午9:59

def foo():
    print('ok')
    yield 1

g = foo()
print(g)

/home/smoke/PycharmProjects/pythonProject/venv/bin/python /home/smoke/PycharmProjects/pythonProject/lean_python/generator.py
<generator object foo at 0x7f81759c9970>

Process finished with exit code 0

#!/usr/bin/env python3.8
# __author: "smoke"
# date: 2021/1/15 下午9:59

def foo():
    print('ok')
    yield 1

g = foo()
print(g)

next(g)

/home/smoke/PycharmProjects/pythonProject/venv/bin/python /home/smoke/PycharmProjects/pythonProject/lean_python/generator.py
<generator object foo at 0x7fb2d513d970>
ok

Process finished with exit code 0

#!/usr/bin/env python3.8
# __author: "smoke"
# date: 2021/1/15 下午9:59

def foo():
    print('ok')
    yield 1
    print('ok2')
    yield 2

g = foo()
print(g)

next(g)
next(g)

/home/smoke/PycharmProjects/pythonProject/venv/bin/python /home/smoke/PycharmProjects/pythonProject/lean_python/generator.py
<generator object foo at 0x7f737bfe2970>
ok
ok2

Process finished with exit code 0

#!/usr/bin/env python3.8
# __author: "smoke"
# date: 2021/1/15 下午9:59

def foo():
    print('ok')
    yield 1
    print('ok2')
    yield 2

g = foo()
print(g)

next(g)
next(g)
next(g)

/home/smoke/PycharmProjects/pythonProject/venv/bin/python /home/smoke/PycharmProjects/pythonProject/lean_python/generator.py
Traceback (most recent call last):
  File "/home/smoke/PycharmProjects/pythonProject/lean_python/generator.py", line 16, in <module>
    next(g)
StopIteration
<generator object foo at 0x7fba927f7970>
ok
ok2

Process finished with exit code 1

#!/usr/bin/env python3.8
# __author: "smoke"
# date: 2021/1/15 下午9:59

def foo():
    print('ok')
    yield 1
    print('ok2')
    yield 2

g = foo()
print(g)

for i in foo():
    print(i)

/home/smoke/PycharmProjects/pythonProject/venv/bin/python /home/smoke/PycharmProjects/pythonProject/lean_python/generator.py
<generator object foo at 0x7f35c01d5970>
ok
1
ok2
2

Process finished with exit code 0

#!/usr/bin/env python3.8
# __author: "smoke"
# date: 2021/1/15 下午9:59

def foo():
    print('ok')
    yield 1    #返回值,类似return 1
    print('ok2')
    yield 2

g = foo()
print(g)

print(next(g))
print(next(g))

/home/smoke/PycharmProjects/pythonProject/venv/bin/python /home/smoke/PycharmProjects/pythonProject/lean_python/generator.py
<generator object foo at 0x7ff2a4e91970>
ok
1
ok2
2

Process finished with exit code 0

什么是可迭代对象,有__iter__()方法

#!/usr/bin/env python3.8
# __author: "smoke"
# date: 2021/1/15 下午9:59

#什么是可迭代对象,有__iter__()方法
l = [1,2,3]
l.__iter__()

t = (1,2,3)
t.__iter__()

d = {'name':'123'}
d.__iter__()

斐波拉契数列

#!/usr/bin/env python3.8
# __author: "smoke"
# date: 2021/1/15 下午9:59

# 0 1 1 2 3 5 8 13 21

def fib(max):
    n, before, after = 0, 0, 1
    while n < max:
        print(after)
        before, after = after, before + after
        n = n + 1

fib(10)

/home/smoke/PycharmProjects/pythonProject/venv/bin/python /home/smoke/PycharmProjects/pythonProject/lean_python/generator.py
1
1
2
3
5
8
13
21
34
55

Process finished with exit code 0

#!/usr/bin/env python3.8
# __author: "smoke"
# date: 2021/1/15 下午9:59

# 0 1 1 2 3 5 8 13 21

def fib(max):
    n, before, after = 0, 0, 1
    while n < max:
        print(after)
        # before, after = after, before + after
        old_before = before
        before = after
        after = old_before + after
        n = n + 1

fib(10)

/home/smoke/PycharmProjects/pythonProject/venv/bin/python /home/smoke/PycharmProjects/pythonProject/lean_python/generator.py
1
1
2
3
5
8
13
21
34
55

Process finished with exit code 0

#!/usr/bin/env python3.8
# __author: "smoke"
# date: 2021/1/15 下午9:59

# 0 1 1 2 3 5 8 13 21

def fib(max):
    n, before, after = 0, 0, 1
    while n < max:
        print(before)
        # before, after = after, before + after
        old_before = before
        before = after
        after = old_before + after
        n = n + 1

fib(8)

/home/smoke/PycharmProjects/pythonProject/venv/bin/python /home/smoke/PycharmProjects/pythonProject/lean_python/generator.py
0
1
1
2
3
5
8
13

Process finished with exit code 0

#!/usr/bin/env python3.8
# __author: "smoke"
# date: 2021/1/15 下午9:59

# 0 1 1 2 3 5 8 13 21

def fib(max):
    n, before, after = 0, 0, 1
    while n < max:
        # print(before)
        yield before
        # before, after = after, before + after
        old_before = before
        before = after
        after = old_before + after
        n = n + 1

print(fib(8))

/home/smoke/PycharmProjects/pythonProject/venv/bin/python /home/smoke/PycharmProjects/pythonProject/lean_python/generator.py
<generator object fib at 0x7f0d1a8a0970>

Process finished with exit code 0

#!/usr/bin/env python3.8
# __author: "smoke"
# date: 2021/1/15 下午9:59

# 0 1 1 2 3 5 8 13 21

def fib(max):
    n, before, after = 0, 0, 1
    while n < max:
        # print(before)
        yield before
        # before, after = after, before + after
        old_before = before
        before = after
        after = old_before + after
        n = n + 1

g = fib(8)
print(g)

print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))

/home/smoke/PycharmProjects/pythonProject/venv/bin/python /home/smoke/PycharmProjects/pythonProject/lean_python/generator.py
<generator object fib at 0x7f44890ef970>
0
1
1
2
3

Process finished with exit code 0

#!/usr/bin/env python3.8
# __author: "smoke"
# date: 2021/1/15 下午9:59

# 0 1 1 2 3 5 8 13 21

def fib(max):
    n, before, after = 0, 0, 1
    while n < max:
        # print(before)
        yield before
        # before, after = after, before + after
        old_before = before
        before = after
        after = old_before + after
        n = n + 1

g = fib(8)
print(g)

print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))

/home/smoke/PycharmProjects/pythonProject/venv/bin/python /home/smoke/PycharmProjects/pythonProject/lean_python/generator.py
<generator object fib at 0x7f2436b5a970>
0
1
1
2
3
5
8
13
Traceback (most recent call last):
  File "/home/smoke/PycharmProjects/pythonProject/lean_python/generator.py", line 29, in <module>
    print(next(g))
StopIteration

Process finished with exit code 1

send()

#!/usr/bin/env python3.8
# __author: "smoke"
# date: 2021/1/15 下午9:59

def bar():
    print('ok1')
    yield 1

    print('ok2')
    yield 2

b = bar()
next(b)

/home/smoke/PycharmProjects/pythonProject/venv/bin/python /home/smoke/PycharmProjects/pythonProject/lean_python/generator.py
ok1
ok2

Process finished with exit code 0

#!/usr/bin/env python3.8
# __author: "smoke"
# date: 2021/1/15 下午9:59

def bar():
    print('ok1')
    count = yield 1
    print(count)
    print('ok2')

    yield 2

b = bar()

b.send(None)    #next(b)

/home/smoke/PycharmProjects/pythonProject/venv/bin/python /home/smoke/PycharmProjects/pythonProject/lean_python/generator.py
ok1

Process finished with exit code 0

#!/usr/bin/env python3.8
# __author: "smoke"
# date: 2021/1/15 下午9:59

def bar():
    print('ok1')
    count = yield 1
    print(count)
    print('ok2')

    yield 2

b = bar()

s = b.send(None)    #next(b),第一次send前没有next()只能传一个send(None)
print(s)

/home/smoke/PycharmProjects/pythonProject/venv/bin/python /home/smoke/PycharmProjects/pythonProject/lean_python/generator.py
ok1
1

Process finished with exit code 0

#!/usr/bin/env python3.8
# __author: "smoke"
# date: 2021/1/15 下午9:59

def bar():
    print('ok1')
    count = yield 1
    print(count)

    yield 2

b = bar()


b.send(None)    #next(b)
b.send('eeee')

#!/usr/bin/env python3.8
# __author: "smoke"
# date: 2021/1/15 下午9:59

def bar():
    print('ok1')
    count = yield 1
    print(count)

    yield 2

b = bar()


next(b)
ret = b.send('eeee')
print(ret)

/home/smoke/PycharmProjects/pythonProject/venv/bin/python /opt/pycharm/pycharm-2020.2.3/plugins/python/helpers/pydev/pydevd.py --multiproc --qt-support=auto --client 127.0.0.1 --port 39905 --file /home/smoke/PycharmProjects/pythonProject/lean_python/generator.py
Connected to pydev debugger (build 203.6682.179)
ok1
eeee
2

Process finished with exit code 0