共同点:return和yield都用来返回值;在一次性地返回所有值场景中return和yield的作用是一样的。
不同点:如果要返回的数据是通过for等循环生成的迭代器类型数据(如列表、元组),return只能在循环外部一次性地返回,yeild则可以在循环内部逐个元素返回。下边我们举例说明这个不同点。
下面通过实例对比return和yield
class TestYield:
def gen_iterator(self):
result_list = []
for j in range(3):
print(f"gen_iterator-{j}")
result_list.append(j)
# return在循环的外部,待变量完全生成后一次性返回
return result_list
def call_gen_iterator(self):
# 执行下边这句后result_list直接是完成的结果[0,1,2]
result_list = self.gen_iterator()
for i in result_list:
print(f"call_gen_iterator-{i}")
if __name__ == "__main__":
obj = TestYield()
obj.call_gen_iterator()
输出结果:
gen_iterator-0
gen_iterator-1
gen_iterator-2
call_gen_iterator-0
call_gen_iterator-1
call_gen_iterator-2
直接把return改为yield
class TestYield:
def gen_iterator(self):
result_list = []
for j in range(3):
print(f"gen_iterator-{j}")
result_list.append(j)
yield result_list
def call_gen_iterator(self):
# 执行下边这句后result_list直接是完成的结果[0,1,2]
result_list = self.gen_iterator()
for i in result_list:
print(f"call_gen_iterator-{i}")
if __name__ == "__main__":
obj = TestYield()
obj.call_gen_iterator()
输出结果:
gen_iterator-0
gen_iterator-1
gen_iterator-2
call_gen_iterator-[0, 1, 2]
在gen_iterator中yield和return的值是一样的,说明yield在一次性返回所有值时,他们的作用一样。
将result_list 改为 j
class TestYield:
def gen_iterator(self):
for j in range(3):
print(f"do_something-{j}")
# yield在for循环内部
yield j
def call_gen_iterator(self):
# yield并不是直接返回[0,1,2],执行下边这句后result_list什么值都没有
result_list = self.gen_iterator()
# i每请求一个数据,才会触发gen_iterator生成一个数据
for i in result_list:
print(f"call_gen_iterator-{i}")
if __name__ == "__main__":
obj = TestYield()
obj.call_gen_iterator()
结果为:
do_something-0
call_gen_iterator-0
do_something-1
call_gen_iterator-1
do_something-2
call_gen_iterator-2
可以看到:上下函数是交替运行的,这说明上层函数请求迭代一个值,下层函数才生成一个值,并立即返回这个值。