CSIC_716_20191113【装饰器进阶以及迭代器】
装饰器的进阶主要包含叠加装饰器和有参装饰器
叠加装饰器:在一个被装饰的对象中,添加多个装饰器。
为什么要用叠加装饰器的原因: -每一个新的功能都应该写一个新的装饰器,否则会导致,代码冗余,结构不清晰,可扩展性差。
理解叠加装饰器的工作原理:装饰的时候就近原则,从下到上装饰,将函数包装起来。调用的时候自上往下执行最后,在最上层装饰器中return结束。
有参装饰器:
装饰中要传递参数,用三层结构的装饰器即可将参数传递。
@wrapper('参数')
有参装饰器的固定句式(一个参数)
# _*_ coding: gbk _*_ # @Author: Wonder def certified(paramater): #这里只试验一个参数 def wrapper(func): def inner(*args,**kwargs): if('# 对paramater做个判断'): #做一波条件成立的操作 res = func(*args, **kwargs) return res else: #做条件不成立的操作 res = func(*args, **kwargs) return res return inner return wrapper @certified('paramater') # 传参数,这里只试验一个参数 def func(): print('做一波func的操作') return func( ) # 调用
传多个参数的时候,在装饰器内部写入多种判断情况。可以拷贝被装饰对象,并在其上方添加参数不同的装饰器,即可实现多种判断。
wraps:是一个修复工具,修复的是被装饰对象的空间。在装饰过程中,将装饰器中的闭包函数加入
导入from functools import wraps,用法:在装饰器闭包函数上面
#6.请实现一个装饰器,限制该函数被调用的频率,如10秒一次
import time from functools import wraps runed_time = [0] def wrapper(func): @wraps(func) def inner(*args, **kwargs): hz = int(time.time()) if hz - runed_time[0] > 10: # 查看当前执行时间和上次执行时间之差 print('没等') res = func(*args, **kwargs) runed_time[0] = hz return res else: print('登陆中...') p = 10 - (hz - runed_time[0]) time.sleep(p) runed_time[0] = hz print(f'else等候了{p}秒') res = func() return res return inner @wrapper def drug(): print('执行一次') while True: input('>>>') drug()
# 函数对象.__doc__: 查看函数内部的注释
迭代器
迭代:迭代指的是重复迭代,每一次迭代都是基于上一次的结果而来的。
迭代器:迭代器指的是迭代取值的工具,它可以迭代取值
可迭代对象,字符串str、列表list、元组tuple、字典dict、集合set、文件f
可迭代对象可以通过 .__iter__()变成迭代器对象。
迭代器对象可以通过 .__next__()取值。
可迭代对象不一定是迭代器对象。 只有文件f是迭代器对象,其他都不是迭代器对象。
迭代器对象都是可迭代对象。
迭代器取值示范:
# _*_ coding: gbk _*_ # @Author: Wonder list1 = [0, 1, 2, 3, 4] iter_list1 = list1.__iter__() # 可迭代对象变迭代器对象 while True: try: print(iter_list1.__next__()) except StopIteration: # 捕获异常 break
迭代器的优点:
1.节省内存空间
2.提供了一种不依赖索引取值的方式
缺点:
1.无法通过len()方法计算长度
2.取指定位置的值非常麻烦
3.每次取值都从第一位开始,不可以索引取值
for循环的原理
for i in 可迭代对象
in的操作 将可迭代对象.__iter__()转变为迭代器对象,
再将迭代器对象.__next__(),对迭代器对象取值。
可迭代对象不一定都是迭代器对象,因为除文件之外的可迭代对象都不是迭代器对象
迭代器对象都是可迭代对象。
可迭代对象都有 .__iter__( )方法
迭代器对象都有.__next__( )的取值方法