装饰器
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 = inner
index() # 此时 index() 在执行 inner 函数
@test_time
def func1():
time.sleep(2)
print('欢迎访问日记首页')
@test_time
def 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 True
print(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 + b
print(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 wrapper
def 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 inner1
def 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 == inner1
def f():
print('in f') # 3
f() # inner2()
# 从上往下执行函数前的操作,从下往上执行函数后的操作,中间执行函数
递归函数
递归函数:函数或者其他代码都可以解决递归解决的问题,但是递归在某些时候能出奇制胜的效果
通俗点说,就是函数在自己内部调用自己。
递归函数举例
# 初识递归。
def func(n):
print(n)
n += 1
func(n)
func(1)
# 官网规定:默认递归的最大深度1000次。
# 如果你递归超过100次还没有解决这个问题,那么执意使用递归,效率很低。
'''
下边的每一个人都比上一个大两岁,计算第四个人的年龄
1 太白 18
2 景女神 18 + 2
3 宝元 18 + 2 + 2
4 alex 18 + 2+ 2+2 age(4) = age(3) + 2
'''
def age(n):
if n == 1:
return 18
else:
return age(n-1) + 2
print(age(4))
'''递归内部运算
def age(4):
if n == 1:
return 18
else:
return age(3) + 2
age(4) = age(3) + 2
def age(3):
if n == 1:
return 18
else:
return age(2) + 2
age(4) = age(2) + 2 + 2
def age(2):
if n == 1:
return 18
else:
return age(1) + 2
age(4) = age(1) + 2 + 2 + 2
def age(1):
if n == 1:
return 18
else:
return age(1) + 2
age(4) = 18 + 2 + 2 + 2
'''
l1 = [1, 3, 5, ['太白','元宝', 34,],66]
# 将l1以下面的形式展现在屏幕上
'''
1
3
5
'太白'
'元宝'
34
66
'''
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)
# 这样无论列表嵌套多少层,这个函数都能解决