大家都知道,python中有三大式,和三大器,前篇博客稍微举例说明了一下三大推导式,本篇文章也一样,稍微举例说明一下三大器:迭代器,生成器,装饰器。
迭代器
我们知道像string、list、tuple、set、dictionary等容器对象可以使用for循环迭代。那为什么可以迭代呢,调用了什么方法呢。
举例:
for num in [10,20,30,40,50]:
print(num)
1、在for循环中调用了list的__iter__()方法。这个方法返回一个迭代器对象。迭代器对象有一个方法__next__(),该方法返回list容器中的下一项。
2、当所有项都被迭代后,下一次调用__next__()将引发一个StopIteration异常,该异常将告诉for循环终止。
上面的例子中,也可以使用__iter__()和__next__()得到相同的结果。
lst = [10, 20, 30, 40, 50]
i = lst.__iter__()
print(i.__next__())
print(i.__next__())
print(i.__next__())
print(i.__next__())
print(i.__next__())
还可以调用更方便的iter()和next()来实现。
lst = [10, 20, 30, 40, 50]
i = iter(lst)
print(next(i))
print(next(i))
print(next(i))
print(next(i))
print(next(i))
1、可迭代器对象是一个能够一次返回一个成员的对象。
2、迭代器是一个同时在其内部实现了__iter__()和__next__()的对象。
生成器
生成器是一个用于创建迭代器非常高效的函数。当生成器希望从函数返回数据时,使用yield语句而不是return。
生成器的特殊之处在于,当yield被执行时,它会记住函数的状态以及执行的最后一条语句。因此,每次调用next()时,都会从上次中断的地方恢复。
生成器非常简洁,因为__iter__()、next()和StopIteration代码是自动创建的。
举例:
# 求列表内相邻两数的平均值
def Avg(data):
for i in range(0, len(data)-1):
yield (data[i]+data[i+1])/2
lst = [10, 20, 30, 40, 50, 60, 70]
for i in Avg(lst):
print(i)
#结果如下:
15.0
25.0
35.0
45.0
55.0
65.0
生成器表达式
与列表推导式类似,为了使代码更紧凑、更简洁,可以编写紧凑的生成器表达式。
生成器表达式动态地创建一个生成器,而不需要使用yield语句。
举例:
# 生成10到100之间的20个随机数
print(max(random.randint(10,100) for n in range(20)))
# 打印所有小于20的数字的立方和
print(sum(n*n*n for n in range(20)))
注意:不像列表推导式用[]包围,生成器表达式写在()中。
装饰器
函数是python的“一等公民”。这意味着像整数、字符串、列表、模块等函数也可以动态创建和删除,传递给其它函数并作为值返回。
在装饰器中也使用了“一等公民”特性。
装饰器函数接收一个函数,向它添加一些功能(装饰)并返回它。
常用的装饰器有@classmethod、@staticmethod、@property。
举例:
定义一个装饰器,可以报告执行任何函数所需的时间。
import time
def timer(func):
def calculate(*args, **kwargs):
start_time = time.perf_counter()
value = func(*args, **kwargs)
end_time = time.perf_counter()
runtime = end_time - start_time
print(f'函数所需时间{runtime:.8f}秒')
return value
return calculate
@timer
def product(num):
fact = 1
for i in range(num):
fact = fact *i+1
return fact
@timer
def product_and_sum(num):
p = 1
for i in range(num):
p = p *i+1
s = 0
for i in range(num):
s = s + i + 1
return (p, s)
@timer
def time_pass(num):
for i in range(num):
i +=1
p = product(10)
print('product of first 10nos.=', p)
p = product(20)
print('product of first 20nos.=', p)
fs = product_and_sum(10)
print('product and sum of first 10 nos.=', fs)
fs = product_and_sum(20)
print('product and sum of first 20 nos.=', fs)
time_pass(20)
#结果如下:
函数所需时间0.00000420秒
product of first 10nos.= 986410
函数所需时间0.00000327秒
product of first 20nos.= 330665665962404000
函数所需时间0.00000327秒
product and sum of first 10 nos.= (986410, 55)
函数所需时间0.00000467秒
product and sum of first 20 nos.= (330665665962404000, 210)
函数所需时间0.00000187秒
1、三个执行时间的函数: product()、time_pass()、product_and_sum()。参数和返回类型各不相同。却能够将相同的装饰器@timer应用到所有的对象上。
2、调用三个函数时传递的参数在*args, **kwargs中接收。
3、被调用的函数回返值在value中收集返回。
4、使用性能计数器,time.perf_counter()返回性能计数器的值,即小数形式的秒数值。函数两次调用之间的差异决定了执行一个函数所需的时间。
5、用类似的方法,可以为类中的方法定义装饰器。