1.本质:装饰器的本质就是函数,为其他函数添加附加功能
原则:
1.不修改被修饰函数的源代码
2.不修改被修饰函数的调用方式
装饰器=高阶函数+函数嵌套(函数的内部又定义了一个函数)+闭包(将变量封存到一个包内,既变量加函数(函数即变量))
高阶函数的定义:
1.函数接收的参数是一个函数名
2.函数的返回值是一个函数名
3.满足上述条件任意一个,都可称之为高阶函数
import time def foo(): time.sleep(2) print('你好') def test(func): start_time = time.time() func() stop_time = time.time() print('运行时间为%s' % (stop_time-start_time)) test(foo)
函数嵌套:
def father(x): print('baba',x) def son(): print('erzi') def grandson(): print('sunzi') grandson() son() print(locals()) father('a')
此时输出值为:
baba a
erzi
sunzi
{'x': 'a', 'son': <function father.<locals>.son at 0x0000029794AF21F0>}
!!!注意函数的作用域!!!先找最近的变量
装饰器实现:
原先的代码:
import time def timmer(func): def wrapper(): start_time = time.time() func() stop_time = time.time() print('运行时间是%s' %(stop_time-start_time)) return wrapper def test(): time.sleep(0.1) print('执行啦') test = timmer(test) #此时传回来的是wrapper的内存地址 test() #这里执行的是warpper
修改后:
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 #相当于 test = timmer(test)
def test():
time.sleep(0.1)
print('执行啦')
a = test() #此处先执行timmer(test),得到wrapper的内存地址, 然后执行wrapper,wrapper里func()执行了下方的test(),然后得到一个返回值,拿res接收,再返回给了wrapper
print(a) #此时就得到了test()的返回值“这是test的返回值”
装饰器加上参数: 用*args,**kwargs来接收多个变量
import time def timmer(func): def wrapper(*args,**kwargs): # *args以元组的形式接收,**kwargs接收字典 start_time = time.time() res = func(*args,**kwargs) #执行test(),然后将test()里的返回值接收 stop_time = time.time() print('运行时间是%s' %(stop_time-start_time)) return res return wrapper @timmer #相当于 test = timmer(test) def test(name,age): time.sleep(0.1) print('执行啦,%s,%s'%(name,age)) return '这是test的返回值' test('chris',18)
此时输出值为:
执行啦,chris,18
运行时间是0.10074973106384277
解压序列与值的交换
l = [1,2,5,76,86,34,64] a,b,*_,d = l print(a,b,d) f1 = 4 f2 = 7 f1,f2 = f2,f1 print(f1,f2)
此时输出值为:
1 2 64
7 4
!!!*_表示中间的所有值
京东主页认证功能:
user_list = [ {'name':'alex','passwd':'123'}, {'name':'joe','passwd':'123'}, {'name':'chris','passwd':'123'}, {'name':'john','passwd':'123'}, ] current_user = {'username':None,'login':False} def auth(auth_type = 'filedb'): def auth_func(func): def wrapper(*args,**kwargs): print('认证类型为',auth_type) if auth_type == 'filedb': if current_user['username'] and current_user['login']: res = func(*args, **kwargs) print(res) return res num = input('请输入账号:').strip() passwd = input('请输入密码:').strip() for i in user_list: if num == i['name'] and passwd == i['passwd']: current_user['username'] = num current_user['login'] = True res = func(*args,**kwargs) return res else: print('账号或密码错误') elif auth_type == 'ldap': print('玩不来') else: print('啥类型,不知道') return wrapper return auth_func @auth(auth_type = 'filedb') #直接执行了auth()函数,然后返回的值就是auth_func ---> 相当于@auth_func def index(): print('你好产品经理') return '帅得很'
@auth(auth_type = 'asd') def home(): print('欢迎回家') index() home()