一:普通装饰器
- 概念:在不改变原函数内部代码的基础上,在函数执行之前和之后自动执行某个功能,为已存在的对象添加某个功能
- 普通装饰器编写的格式
def 外层函数(参数) def 内层函数(*args,**kwargs) #函数执行之前 data= 参数(*args,**kwags) #函数执行之后 return data return 内层函数
- 用法示例:
def func(arg): def inner(*args,**kwargs): v = arg(*args,**kwargs) return v return inner @func #@装饰器的语法 : 等价于: index = func(index) def index(): print(123) return 666 ret = index() print(ret) 执行原理: 1. 函数从上往下执行,遇到 @func 时,执行 index = func(index),参数 arg = index,同时将返回值 inner 函数赋值给 index , 2. 遇到 index()时,此时就是 inner(),执行 inner 函数 3. 执行 inner 函数,里面的 arg(*args,**kwargs)执行,就是 index 函数执行,打印 123 ,同时将 index 的返回值 666 赋值给 v : v = 666 4. 继续执行 inner 函数, inner 函数的返回值是 v , 执行 inner 函数的是 ret = index() , 所以 ret = v = 666
- 应用示例
#示例:计算函数执行时间 import time def base(func): def inner(*args,**kwargs): start_time = time.time() --->#函数执行之前 v= func(*args,**kwargs) end_tme = time.time() ---->#函数执行之后 print(end_time-start_time) return v return inner @base def func1(): time.sleep(2) # 函数执行延缓2秒 print(123) @base def func2(): time.sleep(1) print(456)
- 关于返回值
def base(func): def inner(*args,**kwargs): data = func(*args,**kwargs) return data return inner @base def index(): print(123) return 666 v1 =index() print(v1) #func函数带括号,执行index函数,先打印'123',先将666返回给data,data再返回给v1
- 关于前后
def base(func): def inner(*args,**kwargs) print('函数调用之前') data = func(*args,**kwargs) #执行原函数并获取返回值 print('调用原函数之后') return data return inner @base def index() print(123) index()
二:带参数的装饰器
- 基本格式
def base(counter): def wrapper(func): def inner(*args,**kwargs): data = func(*args,**kwargs) # 执行原函数并获取返回值 return data return inner return wrapper @base(9) def index(): pass # 先执行base函数,然后将返回值wrapper返回,变成不带参数的装饰器 # counter 参数在装饰器内部任意位置都能被调用
- 用法示例
#写一个带参数的函,实现:参数是多少,被装饰的函数就要执行多少次,返回最后一次执行的结果 def base(counter): def wrapper(func): def inner(*args,**kwargs): for i in range(counter): data = func(*args,**kwargs) # 执行原函数并获取返回值 return data return inner return wrapper @base(5) def index(): return '好难啊' v = index() print(v)
三:生成器 (函数的变异)
- 概念:函数中如果存在yield,那么该函数就是一个生成器函数,调用生成器函数,会返回一个生成器,生成器只有被for循环时,生成器内部代码才会执行,每次循环都会获取yield返回的值
- 获取生成器的三种方式
- 生成器函数
- 生成器表达式
- python内部提供的一些
- 生成器的本质就是迭代器
- 唯一区别: 生成器是我们自己用python代码构建的数据结构,迭代器都是提供的或者是转化得来的
- 生成器函数 : 内部是否包含yield
def func(): print('F1') yield 1 print('F2') yield 2 print('F3') #函数内部代码不会执行,返回一个生成器对象 v1 = func() #生成器可以被for 循环,一旦开始循环函数内部代码就开始执行 for item in v1: print(item) # F1 1 F2 2 F3
- 特殊的迭代对象
def func(): yield 1 v = func() result = v.__iter__() print(result)
四:迭代器
- 概念:对某种对象(str/lsit/tuple/dict/set类创建的对象)中的元素进行逐一获取,表象:具有
__nest__
方法且每次调用都获取可迭代对象中的元素 - 优点 : 节省内存,惰性机制
- 缺点 : 不直观,速度相对慢,操作方法单一,不走回头路
- 列表转换成迭代器
v1 = iter([1,2,3,4])
v2 = [1,2,3,4].
__iter__
()
- 迭代器想要获取每个元素 : 反复调用val = v1.
__next__
()v1 = "alex" v2 = iter(v1) while True: try: val = v2.__next__() print(val) except StopIterationas e: break
- 直到报错:stoplteration错误,表示迭代已经完毕
- 如何判断一个对象是否是迭代器 : 内部是否有
__next__
方法 - for 循环
v1 = [11,22,33,44] # 1.内部会将v1转换成迭代器 # 2.内部反复执行 迭代器.__next__() # 3.取完不报错 for item in v1: print(item)
- 可迭代对象
内部具有
_iter__
方法且返回一个迭代器可以被for 循环