python3学习之路(13) 装饰器
什么是装饰器
装饰即修饰,意指为其他函数添加新功能;器即函数。
装饰器本质就是函数,功能是代码运行期间动态增加函数的功能的方式称之为装饰器。
装饰器遵循的原则
1、不修改被修饰函数的源代码
2、不修改被修饰函数的调用方式
#以下是一个显示函数运行时间的修饰器
import time
def timmer(func): #func=test
def wrapper():
# print(func)
start_time=time.time()
func() #就是在运行test()
stop_time = time.time()
print('运行时间是%s' %(stop_time-start_time))
return wrapper
@timmer #test=timmer(test)
def test():
time.sleep(3)
print('test函数运行完毕')
test()
实现装饰器的知识储备:装饰器 = 高阶函数 + 函数嵌套 + 闭包
高阶函数的定义(满足以下条件任意一个,都可称之为高阶函数):
1、函数接收的参数是一个函数名
2、函数的返回值时一个函数名
#高阶函数例子
def foo():
print('我的函数名作为参数传给高阶函数')
def gao_jie1(func):
print('我就是高阶函数1,我接收的参数名是%s' %func)
func()
def gao_jie2(func):
print('我就是高阶函数2,我的返回值是%s' %func)
return func
gao_jie1(foo)
gao_jie2(foo)
#把函数当做参数传给高阶函数
import time
def foo():
print('from the foo')
def timmer(func):
start_time=time.time()
func()
stop_time=time.time()
print('函数%s 运行时间是%s' %(func,stop_time-start_time))
timmer(foo)
#总结:我们确实为函数foo增加了foo运行时间的功能,但是foo原来的执行方式是foo(),现在我们需要调用高阶函数timmer(foo),改变了函数的调用方式
#把函数名当做参数传给高阶函数,高阶函数直接返回函数名
import time
def foo():
print('from the foo')
def timmer(func):
start_time=time.time()
return func
stop_time=time.time()
print('函数%s 运行时间是%s' %(func,stop_time-start_time))
foo=timmer(foo)
foo()
#总结:我们确实没有改变foo的调用方式,但是我们也没有为foo增加任何新功能
高阶函数总结:
1.函数接收的参数是一个函数名
作用:在不修改函数源代码的前提下,为函数添加新功能,
不足:会改变函数的调用方式
2.函数的返回值是一个函数名
作用:不修改函数的调用方式
不足:不能添加新功能
函数嵌套
def father(name):
print('from father %s' %name)
def son():
print('from son')
def grandson():
print('from grandson')
grandson()
son()
father('erbiao')
闭包
#闭包:在一个作用域里放入定义变量,相当于打了一个包
def father(name):
def son():
# name='alex'
print('我爸爸是 [%s]' %name)
def grandson():
# name='wupeiqi'
print('我爷爷是 [%s]' %name)
grandson()
son()
father('erbiao')
一个简单的装饰器
import time
def timmer(func): # func = test
def wrapper():
start_time = time.time
func() #运行test()
stop_time = time.time
print(“运行时间是 %s”,%(stop_time-start_time))
return wrapper
@timmer
def test():
time.sleep(5)
print("test函数运行完毕")
test()
#不使用装饰器时,调用方法如下:
# res = timmer(test) #返回wrapper地址
# tes() #执行wrapper()
为装饰器加上返回值
#函数默认返回值是None
#以上函数test()若想定义返回值,则需要在timmer()中使用return语句
#因为使用装饰器后,test()函数运行在最后一行在timmer()中,如:
import time
def timmer(func):
def wrapper():
start_time = time.time()
res = func()
stop_time =time.time()
print("函数的运行时间是 %s" %(stop_time - start_time))
return res
return wrapper
@timmer
def test():
time.sleep(3)
print("test函数已运行完毕")
return "这是test()的返回值"
print(test())
装饰器传参实例
#一个简单的装饰器传参实例
#最终函数会在装饰器函数中运行,因此传参要传入装饰器函数
#装饰器在传参时,要保证和函数穿的参数数量一致
import time
def timmer(func):
def wrapper(name,age):
start_time = time.time()
res = func(name,age)
stop_time =time.time()
print("函数的运行时间是 %s" %(stop_time - start_time))
return res
return wrapper
@timmer
def test(name,age):
time.sleep(3)
print('我是%s,我%s了' %(name,age))
return "这是test()的返回值"
print(test("erbiao","35"))
装饰器传入不定长参数
#在向装饰器传入参数过程中,不同的函数可能传入参数数量不一样
#使用位置参数(*args)和关键字参数(**kwarg)可传入不定长参数
#*args表示传入参数是元组,**kwargs表示传入参数是字典
import time
def timer(func):
def wrapper(*args, **kwargs):
start_time = time.time()
func(*args, **kwargs)
stop_time = time.time()
print('函数[%s],运行时间是[%s]' % (func, stop_time - start_time))
return wrapper
@timer
def test(*args,**kwargs):
print("*args",args)
print("**kwargs",kwargs)
res = test("我","x","y","z",a=1,b=2)
print(res)
装饰器模拟认证功能
user_list=[
{'name':'alex','passwd':'123'},
{'name':'linhaifeng','passwd':'123'},
{'name':'wupeiqi','passwd':'123'},
{'name':'yuanhao','passwd':'123'},
]
current_dic={'username':None,'login':False}
def auth_func(func):
def wrapper(*args,**kwargs):
if current_dic['username'] and current_dic['login']:
res = func(*args, **kwargs)
return res
username=input('用户名:').strip()
passwd=input('密码:').strip()
for user_dic in user_list:
if username == user_dic['name'] and passwd == user_dic['passwd']:
current_dic['username']=username
current_dic['login']=True
res = func(*args, **kwargs)
return res
else:
print('用户名或者密码错误')
return wrapper
@auth_func
def index():
print('欢迎来到京东主页')
@auth_func
def home(name):
print('欢迎回家%s' %name)
@auth_func
def shopping_car(name):
print('%s的购物车里有[%s,%s,%s]' %(name,'奶茶','妹妹','娃娃'))
print('before-->',current_dic)
index()
print('after--->',current_dic)
home('产品经理')
# shopping_car('产品经理')

浙公网安备 33010602011771号