Python生成器

本文详细介绍了Python中的生成器,包括其本质、与迭代器的区别、创建方法、学习目的以及yield的关键用法。通过实例展示了如何使用生成器模拟range函数,并对比了yield和return在功能和行为上的差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、生成器

	'''
	生成器对象:
	1.本质:
	    还是内置有__iter__和__next__的迭代器对象
	2.区别:
	    迭代器对象是解释器自动提供的
	        数据类型/文件对象>>>:迭代器对象
	    生成器对象是程序员(自己)编写出来的
	        代码、关键字>>>:迭代器对象(生成器)
	        
	3.创建生成器的基本语法
	    函数体代码中填写yield关键字
	
	4.学习生成器对象的目的
	    主要是为了优化代码 也是一种不依赖于索引取值的另一方式
	    可以节省数据类型的内存占用空间(主要)
	'''
	'''生成器基本语法'''
	def my_iter():
	    """在函数体代码中填写yield关键字"""
	    print('这是第一行代码')
	    yield 1 # 如果yield后面有数据值 那相当于return一样返回出去
	    print('这是第二行代码')
	    yield 2,3,4 # 如果有多个数据值,用逗号隔开,会组成元组的形式返回出去
	'''
	1.函数体代码中如果有yield关键字
	那么函数名加括号并不会执行函数体代码
	会生成一个生成器对象(迭代器对象)
	'''
	res = my_iter() #第一次加括号调用不会执行函数体代码
	'''使用加括号之后的结果调用__next__才会执行函数体代码'''
	res.__next__() #直接由函数变成了迭代器对象(生成器)
	res.__next__()
	'''每次执行完__next__代码都会停在yield位置,
	下次基于该位置继续往下找第二个yield'''
	res.__next__()  
	# 和迭代器对象一样,当后面没有值继续__next__后会报错:StopIteration

二、生成器练习

	'''生成器练习'''
	'''用生成器来模拟range的三种功能'''
	for i in range(0,10,2):
	    pass
	
	'''先实现两个参数的range的编写'''
	def my_range(start,end):  # 创建一个函数给予两个形参,模拟range的开始和结束
		while start < end:  # 因为开始值不能大于结束值,不然会无限下去
			yield start  # 条件成立后进入返回开始值
			start += 1  # 每次返回完毕后加1

	for i in my_range(0,10):
		print(i,end=' ')
	
	
	'''在实现一个参数的range的编写'''
	def my_range(start,end=None):#一个参数的先设置一个形参,可以在写一个默认参数
	'''end可以不传值,可以直接弄成默认参数,end=None'''
	'''代码层面做判断,将形参数据做替换处理'''
		if not end:  # 如果没有给结束传值
			end = start  # 那么就让结束值等于开始值
			start = 0    # 再让开始值从默认0开始

		while start < end:  # 开始值不能大于结束值
			yield start
			start += 1

	for i in range(10):
		print(i, end=' ')
	
	
	'''最后实现三个参数的range编写'''
	def my_range(start,end=None, step=1):  # 创建一个形参两个关键字参数
	    if step < 1: # 如果间隔小于1的话,相当于只有两个参数 所以给它默认等于1
	        step = 1
	
	    if not end:  # 如果没有传值给end,那就是只有一个参数
	        start = end  # 那么就让end等于start
	        start = 0  # 让start从0开始
	
	    while start < end:  # 开始值不能大于结束值
	        yield start  # 返回开始值
	        start += step  #
	
	for i in my_range(0,20,2):
	    print(i,end=' ')

三、生成器yield的其他用法

	def eat(name,food=None):  # 创建一个函数,一个形参,第二个参数给它默认参数
	    print('%s正在吃.....' % name)
	
	    while True:
	        food = yield  # 关键字yield,变成生成器了
	        print('%s正在吃%s' % (name,food))
	
	
	res = eat('chen')
	print(res)  # <generator object eat at 0x000001DCAD48F0B0>
	res.__next__()  # 调用双下__next__
	res.__next__()  # 这里food值是None

	'send做了两件事情:1. 传值给yield、2. 执行__next__'
	res.send('黄焖鸡米饭')  # send传递值
	res.send('饺子')
	res.send('饺子')
	res.send('饺子')

四、生成器表达式

	'''
	生成器表达式
	目的就是为了节省储存空间
	'''
	
	'''列表表达式'''
	name_list = ['chen','sb','shab']
	'''第一种'''
	res =(name for name in name_list)
	print(list(res))  # ['chen', 'sb', 'shab']
	
	'''第二种'''
	res =[name for name in name_list]  # 直接用中括号来表示,这样省掉转换声明步骤
	print(res)
	

	'''生成器表达式'''
	res =(name for name in name_list)
	print(res) # <generator object <genexpr> at 0x0000020CDFB3F0B0>
	print(res.__next__(),end=' ')
	print(res.__next__(),end=' ')
	print(res.__next__(),end=' ')
	
	
	res = (i**2 for i in range(20))
	'''生成器表达式'''
	print(res.__next__(),end=' ')
	print(res.__next__(),end=' ')
	print(res.__next__(),end=' ')
	
	'''列表表达式'''
	print(list(res))

五、yield和return的对比

	'''yield和return的对比'''
	
	'''
	# yield
	1.代码遇到yield不会停止,而是停住
	2.yield也可以有返回值,并且还支持多个,以元组的形式返回
	3.yield可以把一个函数变成生成器,next取值
	
	# return
	1.代码遇到return就会停止
	2.return可以有返回值并且还支持多个,以元组的形式返回
	'''
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值