大家好,小编来为大家解答以下问题,用python写一个学生信息管理系统,用python写学生信息管理系统,现在让我们一起来看看吧!
一、生成器的本质
生成器是含有yield语句(或yield表达式)的函数所返回的对象。也就是说,要创建一个生成器,我们首先要定义一个函数,该函数内将使用yield表达式或yield语句来表示每次生成的值。该函数的返回值是一个生成器对象,通过把这个函数的返回值赋给一个变量,我们就得到了一个生成器对象变量,对这个对象进行send和next等操作,即可实现生成器的功能。
如下代码创建了一个最简单的生成器。
def g():
while True:
yield 1
a = g()
创建生成器之前,需要编写一个含有yield的函数,这是一种特殊的函数。当该函数被调用时,并不会立即执行函数中语句,而是直接返回一个生成器对象。后续的操作都可以通过生成器对象进行执行。
在这里,变量a就是一个生成器对象。
二、使用next()
next函数可用于引起生成器/迭代器的下一次生成/迭代。其返回值就是下一个生成的值。通过 next(generator) 这一方式,可以获得一系列值。
def g():
a=1
while True:
yield a
a+=1
a=g()
print(next(a))
print(next(a))
print(next(a))
'''
输出:
1
2
3
'''
由示例可见,输出结果为分别为1,2,3. 对于该过程的解释如下:
每调用一次next(a),都将执行g()函数,执行到yield处时,g()函数暂停,并将yield后的表达式作为next(a)的返回值返回。此后继续调用next(a)时,将从上一次g()函数中的暂停处继续运行,直到来到下一个yield,并执行同样的操作,依次类推。
三、StopIteration异常
在第二节中探讨的生成器采用了while True循环,这一生成器可生成的元素是无限多的,但也有只能产出有限个值的生成器,如下例所示:
def g():
yield 1
yield 2
a=g()
print(next(a))
print(next(a))
print(next(a))
该生成器最多产出两个元素,因此在执行最后一个(即第三个)print语句时,将会报错,引发StopIteration异常。
换言之,如果生成器中运行g()函数直到结束还没有yield出现,就会发生StopIteration异常。因此,如果在生成器对应的函数中应用return语句,也会产生同样的效果:
def g():
if(t != 0):
yield t
else:
return
a = g()
t = 1
print(next(a))
t = 0
print(next(a)) # g()在yield之前就已经return了,所以这里会报错
四、生成器函数传参
用于生成器的函数可以携带参数,此时在定义生成器对象时可以带参调用函数,如下所示:
def g(value=0,step=1):
while True:
yield value
value += step
a = g(1,2)
print(next(a))
print(next(a))
print(next(a))
'''
输出:
1
3
5
'''
五、生成器方法send()
这是生成器中一个相对比较难理解的概念。笔者在初学时查阅了很多资料,百思不得其解。但通过简单的代码实验,就了解了send()的使用方法。send()函数可以接收一个参数发送(该参数可以是任意类型的,如字符串、数字、列表等)。
此时,yield作为表达式,而不是语句出现在生成器对应的函数中。
来看下面的示例:
def g():
t = yield 1
yield t
a=g()
print(next(a))
print(a.send("test"))
'''
输出:
1
test
'''
对于本例,可作出如下解释:
第一次print:调用next(a),g()函数执行到t=yield 1暂停(准确的来说由于赋值表达式是从右往左运算的,因此运行到yield 1这个地方就会暂停,此时还没有进行赋值操作),和上例一样,yield充当语句的角色,next()函数返回1,因此打印结果为1
第二次print:调用send("test"),此时,暂停处的 yield 1 将会充当表达式的角色,这个特殊的表达式的值为send函数的参数——即"test",然后t就被赋值为了"test",g()从该处继续运行,直到遇到下一个yield——即yield t语句,send()函数返回t的值,即打印出了test.
从这个例子当中,大家可以思考一个问题send()和next()有什么联系和区别?首先,在形式上,next是函数,可针对迭代器、生成器进行操作,所以语法是next(a)。而send()是生成器独有的方法, 语法是a.send(something)。 此外,send发送一个参数,使得暂停处的yield充当表达式的角色,并通过send()函数传入的参数决定yield表达式的值。
两者的共同点在于,他们都从上一次yield暂停处继续程序,运行到达下一个yield处,并返回该处yield后的值。
值得指出的是,初次使用生成器的时候,由于还没有“上一个yield”,所以不可以通过send()函数传入消息。因此只能使用next(a)。当然,如果非要使用send的话,传入一个None参数,即a.send(None)也是被允许的。