Python 生成器

生成器


image

1. 什么是生成器

生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。

不同于一般的函数会一次性返回包括了所有数值的数组,生成器一次只能产生一个值,这样消耗的内存数量将大大减小,而且允许调用函数可以很快的处理前几个返回值。

2 创建生成器

生成器可以通过生成器表达式和生成器函数获取到

生成器表达式

创建生成器对象和创建列表生成式特别像

# 创建列表生成式
>>> list_num = [x for x in range(10)]
>>> list_num
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# 生成器
>>> glist_num = (x for x in range(10))   # 只需要把中括号换成小括号就成了生成器
>>> glist_num
<generator object <genexpr> at 0x7fc3d7375830>
>>> glist_num.__next__()
0
>>> glist_num.__next__()
1
>>> next(glist_num)
2
>>> next(glist_num)
3

# 生成器表达式内部的代码只有在迭代取值的时候才会执行

使用next()和使用__next__()一样

生成器函数

生成器函数指的是函数体中包含yield关键字的函数

定义生成器函数和定义普通函数一样。

# 1 生成器函数
>>> def my_func():
        print("Hello")
        yield 
    
>>> my_func()
<generator object my_func at 0x7fc3d6c70e08>
>>> res = my_func()
>>> res
<generator object my_func at 0x7fc3d6c70e60>
>>> next(res)
Hello
>>> 
>>> next(res)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

# 生成器函数(yield有返回值)

def my_func():
    print("Hello")
    yield 1

res = my_func()

r = res.__next__()   # 会执行 print("Hello")

print(r)  # r为yield的返回值

# 执行结果:
Hello
1

# 生成器函数(yield多个返回值)
def my_func():
    print("Hello")
    yield 1,2

res = my_func()

r = res.__next__()

print(r)

# 执行结果:
Hello
(1, 2)

#函数中只有一个yield所以只能执行一次__next__()方法
def my_func():
    print("Hello")
    yield 1,2

res = my_func()

print(res.__next__())
print(res.__next__())  # 调用两次就会报错

#执行结果: 
Hello
(1, 2)
Traceback (most recent call last):
  File "b.py", line 8, in <module>
    print(res.__next__())
StopIteration

# 有多个yield
def my_func():
    print("Hello")
    yield 1,2		
    print("world")
    yield 'a','b' 

res = my_func()

print(res.__next__()) # 每执行一个__next__代码往下运行到yield停止 返回后面的数据
print(res.__next__()) # 每执行一个__next__代码往下运行到yield停止 返回后面的数据

注意:当函数体内含有yield关键字 那么在第一次调用函数的时候,并不会执行函数体代码,而是将函数变成了生成器(迭代器).

每执行一个__next__代码往下运行到yield停止 返回后面的数据.

yield不但能返回值,而且还能给它传值

yield传值

使用sendyield传值

示例:

def my_define(name):
    print("%s is doing work" % name)
    while True:
        play  = yield
        print("%s is do %s" %(name, play))


res = my_define("Hans")

res.__next__()
res.__next__()

# 执行结果:
Hans is doing work
Hans is doing None

# 给yield传值:
def my_define(name):
    print("%s is doing work" % name)
    while True:
        play  = yield
        print("%s is do %s" %(name, play))


res = my_define("Hans")

res.__next__()
res.__next__()
# 给yield传两个值:write和coding
res.send("write")
res.send("coding")

# 执行结果:
Hans is doing work
Hans is do None
Hans is do write
Hans is do coding

3 生成器练习

模拟range功能

# 代码
def my_range(start, stop=None, step = 1):
    if not stop:
        stop = start
        start = 0

    while start < stop:
        yield start
        start += step

print("一个参数")
for i in my_range(3):
    print(i)
    
print("两个参数")
for i in my_range(1,3):
    print(i)

print("三个参数")
for i in my_range(1, 10, 2):
    print(i)
# 执行结果:
一个参数
0
1
2
两个参数
1
2
三个参数
1
3
5
7
9

求和(面试题)

# 代码:
def add(n, i):
    return n + i

def test():
    for i in range(4):
        yield i
g = test()
for n in [1, 10]:
    g = (add(n, i) for i in g)
  
res = list(g)
print(res)

#从下面的结果中选择一个:

#A. res=[10,11,12,13]
#B. res=[11,12,13,14]
#C. res=[20,21,22,23]
#D. res=[21,22,23,24]


# 解析:
def add(n, i):
    return n + i
# 调用之前是函数 调用之后是生成器
def test():
    for i in range(4):
        yield i
g = test()  # 初始化生成器对象
for n in [1, 10]:
    g = (add(n, i) for i in g)
    """
    第一次for循环
        g = (add(n, i) for i in g)
    第二次for循环
        g = (add(10, i) for i in (add(10, i) for i in g))
    """
res = list(g)
print(res)

#执行结果为:[20,21,22,23], 答案选C
#A. res=[10,11,12,13]
#B. res=[11,12,13,14]
#C. res=[20,21,22,23]
#D. res=[21,22,23,24]

4 yield和return的区别

yield

  1. 可以返回值(支持多个,并且组织成元组)
  2. 函数体代码遇到yield不会结束而是阻塞
  3. yield可以将函数变成生成器 并且还支持外界传值

return

  1. 可以返回值(支持多个并且组织成元组)
  2. 函数体代码遇到return直接结束

5 生成器和迭代器总结

迭代器对象 生成器对象 我们都可以看成是"工厂",只有当我们所要数据的时候工厂才会加工出"数据"

主要目的就是节省空间

6. Python中内置函数

内置函数
abs() divmod() input() open() staticmethod()
all() enumerate() int() ord() str()
any() eval() isinstance() pow() sum()
basestring() execfile() issubclass() print() super()
bin() file() iter() property() tuple()
bool() filter() len() range() type()
bytearray() float() list() raw_input() unichr()
callable() format() locals() reduce() unicode()
chr() frozenset() long() reload() vars()
classmethod() getattr() map() repr() xrange()
cmp() globals() max() reverse() zip()
compile() hasattr() memoryview() round() import()
complex() hash() min() set()
delattr() help() next() setattr()
dict() hex() object() slice()
dir() id() oct() sorted() exec 内置表达式
内置函数
https://docs.python.org/zh-cn/3/library/functions.html
posted on 2021-11-22 21:00  Hans_Wang  阅读(447)  评论(0编辑  收藏  举报

回到顶部