可以参考迭代器的博客,因为生成器就是一种特殊的迭代器
def gen(num):
while num > 0:
yield num
num -= 1
return
g = gen(5)
print("生成器本身是一种特殊的迭代器,所以也可以使用for loop的方式来迭代")
for i in g:
print(i)
gg = gen(7)
print("生成器也可以使用next方法")
first = next(gg)
for j in gg:
print(j)
结果
生成器本身是一种特殊的迭代器,所以也可以使用for loop的方式来迭代
5
4
3
2
1
生成器也可以使用next方法
6
5
4
3
2
1
经常叫生成器,迭代器很好理解,就是class,但是生成器有所不同
g = gen(5)
g是生成器对象
gen(5)是生成器函数
调用生成器函数会生成一个生成器对象保存到g中,不会返回一个值,只有当你对这个生成器对象使用next函数的时候,他才开始真正运行他的函数本体
当python发现函数中有一个yield的时候,就会把这个函数打上一个标签,说这个是一个生成器函数
运行到yield的时候,把num返回出去了,但是这个函数还没运行完,相当于被按了一个暂停键,下次再运行next的时候,会继续运行yield下面的代码
在运行若干次之后,运行到num=0了,这个时候会运行这个return了,由于在生成器里面,这个return等价于raise StopIteration
从使用者的角度,生成器和迭代器没啥区别,但是在原理上
迭代器是把迭代的状态保存到了对象里
生成器是是把这个状态保存到了frame(栈帧)里,这个函数运行到哪一步了,而不是通过一个变量来存储现在的状态
class NodeIter:
def __init__(self, node):
self.curr_node = node
def __next__(self):
if self.curr_node is None:
# 如果数据已经到头了,就需要抛出错误
raise StopIteration
# 没有到头的话,就返回这个node,并且把下一个值存储
node, self.curr_node = self.curr_node, self.curr_node.next
return node
def __iter__(self):
return self
class Node:
def __init__(self, name):
self.name = name
self.next = None
def __iter__(self):
# Node是一个Iterable,但是他的__iter__方法,返回了一个iterator
return NodeIter(self)
node1 = Node("Node1")
node2 = Node("Node2")
node3 = Node("Node3")
node1.next = node2
node2.next = node3
for node in node1:
# 等于for node in iter(node1),向Iterable要了一个iterator
print(node.name)
上面这个是一个自己写的迭代器,我们接下来给它改造成一个生成器
"""
#!/usr/bin/env python
# -*- coding:utf-8 -*-
@Project : pythonTest
@File : diedaiqi.py
@Author : 张胤
@Date : 2023/5/8 16:23
@Description:
"""
class Node:
def __init__(self, name):
self.name = name
self.next = None
def __iter__(self):
# 直接把这个__iter__函数做成一个生成器,也就是当iter的时候返回的是一个生成器Object,这个生成器Object本身就是一个iterator
node = self
while node is not None:
yield node
node = node.next
node1 = Node("Node1")
node2 = Node("Node2")
node3 = Node("Node3")
node1.next = node2
node2.next = node3
for node in node1:
print(node.name)
生成器相对于迭代器还有一个更高级的用法,就是send
就是在这个生成器yield之后,把这个yiled的什么东西变成一个值,这个值还可以继续复制给生成器
def gen(num):
while num > 0:
yield num
num -= 1
return
gg = gen(7)
print("生成器也可以使用next方法")
first = next(gg)
# gg.send(10)
for j in gg:
print(j)
结果
6
5
4
3
2
1
def gen(num):
while num > 0:
yield num
num -= 1
return
gg = gen(7)
print("生成器也可以使用next方法")
first = next(gg)
gg.send(10)
for j in gg:
print(j)
结果
5
4
3
2
1
def gen(num):
while num > 0:
temp = yield num
# 首先会yield num,然后不管你是next还是send取出来的,会把这个值返回出去,然后接下来拿你send的值,对于生成器来说next(g)和g.send(Node)是一样的
if temp is not None:
num = temp
num -= 1
# return 写不写都可以,毕竟return = return None
gg = gen(7)
print("生成器也可以使用next方法")
first = next(gg)
print(f"send:{gg.send(10)}")
for j in gg:
# next(g)=g.send(Node),tmp会一直被赋值为null,num的值不变
print(j)
# num被赋值成了10,然后又-1,所以下一次yield出来是9
结果
生成器也可以使用next方法
send:9
8
7
6
5
4
3
2
1