一、实验目的
- 迭代器
- 生成器
- 生成器表达式
- 闭包
- 装饰器
二、知识要点
1.迭代器
迭代是Python最强大的功能之一,是访问集合元素的一种方式。迭代器是一个可以记住遍历的位置的对象。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
迭代器有两个基本的方法:iter()
和 next()
。
字符串,列表或元组对象都可用于创建迭代器,例如:
list = [1, 2, 3, 4]
it = iter(list)
print("输出1:", next(it))
print("输出2:", next(it))
输出为:
输出1: 1
输出2: 2
迭代器对象也可以用常规的for
循环语句进行遍历,例如我们在上面的代码后添加:
for x in it:
print(x, end=" ")
最终会输出:
输出1: 1
输出2: 2
3 4
1.1 把一个类作为一个迭代器
把一个类作为一个迭代器需要在类中实现两个方法__iter__()
与__next__()
-
__iter__()
方法:该方法返回一个特殊的迭代器对象,,这个迭代器实现了__next__()
方法并通过Stoplteration
异常标识迭代的完成。 -
__next__()
方法:返回下一个迭代器对象
1.2 StopIteration
异常
StopIteration
异常用于标识迭代的完成,防止出现无限循环的情况,在__next__()
方法中我们可以设置在完成指定循环次数后出发StopIteration
异常来结束迭代。
2.生成器
生成器是一个返回迭代器的函数,只能用于迭代操作,即生成器本质就是一个迭代器,在调用生成器运行的过程中,每次遇到yield
时函数会暂停并保存当前所有的运行信息,返回yield
的值,并在下一次执行next()
方法时从当前位置继续运行。生成器自动创建了__iter__()
和__next__()
方法且当发生器终结时会自动抛出StopIteration
异常。
例如:
# 生成器实现range函数
def range_my(l, h):
while l < h:
yield l
l += 1
for i in range_my(1, 10):
print(i, end=" ")
输出结果为:
1 2 3 4 5 6 7 8 9
由上述代码我们容易得出在While
循环中,每当执行到 yield
语句时,返回变量low
的值并且生成器状态转为挂起。在下一次调用生成器时,生成器从之前冻结的地方恢复执行然后变量low
的值增一。生成器继续while
循环并且再次来到yield
语句…但是请注意:
生成器是无法重复使用的。
例如下面的例子:
# 生成器
def my_generator():
print("Creat my generator")
yield 'a'
yield 'b'
yield 'c'
g = my_generator()
print("第一次使用生成器")
for char in g:
print(char)
print("第二次使用生成器")
for char in g:
print(char)
输出为:
第一次使用生成器
Creat my generator
a
b
c
第二次使用生成器
可以看出,生成器不可重复使用,虽然我们无法创建一个课重复使用的生成器,但是我们可以创建一个对象,将他的__iter__
方法调用而得到一个生成器,例如:
class Object_my(object):
def __init__(self, l, h):
self.l = l
self.h = h
def __iter__(self):
count = self.l
while self.h >= count:
yield count
count += 1
my_obj = Object_my(5, 10)
print("第一次:")
for i in my_obj:
print(i, end=" ")
print("\n第二次:")
for i in my_obj:
print(i, end=" ")
输出为:
第一次:
5 6 7 8 9 10
第二次:
5 6 7 8 9 10
上面的my_obj
并不是生成器或迭代器,因为它不具有__next__
方法,只是一个可迭代对象,生成器是一定不能重复循环的。而my_obj.__iter__()
是一个生成器,因为它是一个带有yield
关键字的函数。
3.生成器表达式
有时简单的生成器可以用简洁的方式调用,就像不带中括号的链表推导式。这些表达式是为函数调用生成器而设计的。生成器表达式比完整的生成器定义更简洁,但是没有那么多变,而且通常比等价的链表推导式更容易记。
例如:
sum(i*i for i in range(10))
输出:285
4.闭包
在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了一个闭包。例如:
def who(name):
def do(what):
print(name, 'do', what)
return do
zz = who('zz')
ln = who('ln')
zz("homework")
ln("housework")
输出:
zz do homework
ln do housework
5.装饰器
装饰器(Decorators)用来给一些对象动态的添加一些新的行为,类似于闭包,例如:
def my_decorator(func):
def wrapper(*args, **kwargs):
print("Before call")
result = func(*args, **kwargs)
print("After call")
return result
return wrapper
@my_decorator
def add(a, b):
#我们的求和函数
return a + b
print(add(1, 3))
输出为:
Before call
After call
4
由于装饰器较为难以理解,我将在之后的文章详细解释。
三、实验内容
1.迭代器
创建一个返回数字的迭代器,初始值为1,逐步递增1
- 代码:
class My_num:
def __iter__(self):
self.a = 1
return self
def __next__(self):
x = self.a
self.a += 1
return x
my_num = My_num()
myiter = iter(my_num)
print(next(my_num))
print(next(my_num))
print(next(my_num))
print(next(my_num))
print(next(my_num))
- 结果:
1
2
3
4
5
2.StopIteration
在20次迭代后停止执行。
- 代码:
class My_stop:
def __iter__(self):
self.a = 1
return self
def __next__(self):
if self.a <= 20:
x = self.a
self.a += 1
return x
else:
raise StopIteration
my_stop = My_stop()
myiter = iter(my_stop)
for x in myiter:
print(x, end=" ")
- 结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
3.生成器
本题要求通过生成器输出斐波那契亚数列前10项
- 代码:
# 生成器的斐波那契亚数列
import sys
def finbonacci(n): # 生成器函数-斐波那契
a, b, counter = 0, 1, 0
while True:
if (counter > n):
return
yield a
a, b = b, a + b
counter += 1
f = finbonacci(10)
while True:
try:
print(next(f), end=" ")
except StopIteration:
sys.exit()
- 结果:
0 1 1 2 3 5 8 13 21 34 55
四、实验结果
无
网友评论