装饰器
1.开放封闭原则
软件面世时,不可能把所有的功能都设计好,当前的未来一两年功能给你上线,定期更新迭代。对于软件之前的写的源代码一般都不会修改,对函数里面的代码以及函数的调用方式。
封闭原则: 不要改变源码。
开放原则:更新增加一些额外的功能。
python中装饰器:完美的诠释的开放封闭原则。
装饰器就是一个函数: 他要装饰一个函数,在不改变原函数的源码以及调用方式的前提下,给其增加一个额外的功能。
2.初识装饰器
# 装饰器函数def test_time(x): # x = index def inner(): start_time = time.time() x() end_time = time.time() print(f'此函数的执行效率{end_time-start_time}') return inner@test_time #与在下面写 index = test_time(index) 效果一样def index(): time.sleep(2) print('欢迎访问博客园首页')# index = test_time(index) # 运行效果 index = innerindex() # 此时 index() 在执行 inner 函数@test_timedef func1(): time.sleep(2) print('欢迎访问日记首页')@test_timedef func2(): time.sleep(1) print('欢迎访问评论首页')# func1 = test_time(func1) #麻烦 每个函数下面都要改函数名 推荐用@# func1 = test_time(func1)func1()func2()
3.被装饰函数带返回值
def test_time(x): # x = index def inner(): start_time = time.time() ret = x() end_time = time.time() print(f'此函数的执行效率{end_time-start_time}') return ret # 返回index() 的返回值给 inner() return inner@test_time # index = test_time(index)def index(): time.sleep(0.5) print('欢迎访问博客园首页') return Trueprint(index()) # inner()# 你应该是让True返回给index()这样才完美了,但是现在index是inner,所以你要是完全不改变原函数的使用,# 你print(index()) ---> True
4.被装饰函数带参数
# 被装饰函数带参数,无论加不加装饰器,你的实参都应该传给形参。# 但以上的版本不能实现传参,index('太白金星') == inner('太白金星')def test_time(x): # x = index def inner(*args,**kwargs): # 函数的定义:* ** 聚合。 # args = ('苹果',) #args = (1, 3) start_time = time.time() ret = x(*args,**kwargs) # 函数的执行:* ** 打散。 # ret = x(*('苹果',)) ==x('苹果') # ret = x(*(1, 3)) ==x(1,3) end_time = time.time() print(f'此函数的执行效率{end_time-start_time}') return ret return inner@test_time # index = test_time(index)def index(n): time.sleep(0.5) print(f'欢迎{n}访问博客园首页') return True@test_time # index = test_time(index)def func2(a,b): time.sleep(0.5) print(f'最终结果:{a+b}') return a + bprint(index('苹果')) # inner('苹果')print(func2(1,3)) # == inner(1,3)
5.标准版装饰器
def warpper(f): # 标准装饰器模板 def inner(*args,**kwargs): '''被装饰函数之前的操作''' # print(666) ret = f(*args,**kwargs) '''被装饰函数之后的操作''' # print('执行完毕了') return ret return inner@warpper # 调用def func(): print(111)
6.带参数的装饰器
def wrapper_out(n,*args,sex='男',): def wrapper(f): # f = func1 def inner(*args,**kwargs): ret = f(*args,**kwargs) # func1() return ret return inner return wrapperdef func1(): print('in func1')func = wrapper_out(1) # 返回值是wrapper函数名ly = func(func1) # 等于wrapper(func1) = inner 返回值ly() # 等于inner()# 使两个函数通过装饰器传参打开两个不同的文件def wrapper_out(n): def wrapper(f): def inner(*args,**kwargs): username = input('请输入用户名:').strip() password = input('请输入密码:').strip() with open(n,encoding='utf-8') as f1: for line in f1: user,pwd = line.strip().split('|') if username == user and password == pwd: print('登陆成功') ret = f(*args,**kwargs) return ret return False return inner return wrapper"""@wrapper_out('qq')def qq(): print('成功访问qq')qq()看到带参数的装饰器分两步执行:@wrapper_out('腾讯') 1. 执行wrapper_out('腾讯') 这个函数,把相应的参数'腾讯' 传给 n,并且得到返回值 wrapper函数名。 2. 将@与wrapper结合,得到我们之前熟悉的标准版的装饰器按照装饰器的执行流程执行。"""@wrapper_out('qq')def qq(): print('成功访问qq')@wrapper_out('tiktok')def tiktok(): print('成功访问抖音')qq()tiktok()# 开发思路:增强耦合性
7.多个装饰器装饰一个函数
def wrapper1(func1): # func1 = f原函数 def inner1(): print('wrapper1 ,before func') # 2 func1() print('wrapper1 ,after func') # 4 return inner1def wrapper2(func2): # func2 == inner1 def inner2(): print('wrapper2 ,before func') # 1 func2() # inner1 print('wrapper2 ,after func') # 5 return inner2@wrapper2 # f = wrapper2(f) 里面的f == inner1 外面的f == inner2@wrapper1 # f = wrapper1(f) 里面的f == func1 外面的 f == inner1def f(): print('in f') # 3f() # inner2()# 从上往下执行函数前的操作,从下往上执行函数后的操作,中间执行函数
递归函数
递归函数:函数或者其他代码都可以解决递归解决的问题,但是递归在某些时候能出奇制胜的效果
通俗点说,就是函数在自己内部调用自己。
递归函数举例
# 初识递归。def func(n): print(n) n += 1 func(n)func(1)# 官网规定:默认递归的最大深度1000次。# 如果你递归超过100次还没有解决这个问题,那么执意使用递归,效率很低。'''下边的每一个人都比上一个大两岁,计算第四个人的年龄1 太白 182 景女神 18 + 23 宝元 18 + 2 + 24 alex 18 + 2+ 2+2 age(4) = age(3) + 2'''def age(n): if n == 1: return 18 else: return age(n-1) + 2print(age(4))'''递归内部运算def age(4): if n == 1: return 18 else: return age(3) + 2age(4) = age(3) + 2def age(3): if n == 1: return 18 else: return age(2) + 2age(4) = age(2) + 2 + 2def age(2): if n == 1: return 18 else: return age(1) + 2age(4) = age(1) + 2 + 2 + 2 def age(1): if n == 1: return 18 else: return age(1) + 2age(4) = 18 + 2 + 2 + 2 '''l1 = [1, 3, 5, ['太白','元宝', 34,],66]# 将l1以下面的形式展现在屏幕上'''135'太白''元宝'3466'''l1 = [1, 3, 5, ['太白','元宝', 34,],66]# 利用双层for循环for i in l1: if type(i) == list: for j in i: print(j) else: print(i)# 但如果列表嵌套的层数比较多,需要多层for循环,代码重复性高,这时就可以用递归# 递归函数def func(alist): for i in alist: if type(i) == list: func(i) # func(['太白','元宝',34]) else: print(i)func(l1)# 这样无论列表嵌套多少层,这个函数都能解决