一 什么是装饰器
装饰器补充:http://www.cnblogs.com/luchuangao/p/6842293.html
器即函数
装饰即修饰,意指为其他函数添加新功能
装饰器定义:本质就是函数,功能是为其他函数添加新功能 #装饰器本身就是函数,被装饰的也是函数。
为什么要用装饰器:
及开放封闭原则。
代码上线后,就是为了尽量避免修改,不修改原函数的源代码和调用方式,并添加新的功能。 # 函数及定义和使用。
装饰器语法:
在被装饰上的正上方写一个@,它会把@这一行下面这一行的函数传递到函数里,再重新赋值给index。
func就是index函数,print(func)返回得是index内存地址。
无参装饰器:
(1):
输出:
welcome to oldboy
run time is 3.000171661376953
执行过程:
# 函数应该先定义后使用。
import time
def timmer(func): # 定义函数就相当于定义变量名,就相当于把函数的代码绑定到一个名字上面了。 #1,定义变量名 #3 func值就是index
def wrapper(): #4 开始执行timmer里面的代码,只要碰到def就跟定义变量名一样,它里边定义的代码全不用管,只要不执行就不用管它。#7
start_time=time.time() #8
# print(func)
func() #9 func就是最原始的index
stop_time=time.time() #14
print('run time is %s' %(stop_time-start_time)) #15
return wrapper #5 return wrapper 就是return wrapper的内存地址
# index=timmer(index)
@timmer #2 timmer要运行timmer(index),所以要跳回去 #10
def index(): #11
time.sleep(3) #12
print('welcome to oldboy') #13
index() #6 index就是wrapper函数,wrapper是一个闭包函数,里边包含了一个状态,就是func。
(2): # 第一次是home,第二次是home("name")
输出:
welcome to dragon home page
run time is 2.0001144409179688
egon 123
run time is 0.0
------------
run time is 0.0
注意:传参数,需要加上*args,**kwargs
(3):
输出:
my_max function
run time is 0.0
-------- 2
注意:如果原函数需要有返回值,则装饰器也需要设置return res。完整正确的无参装饰器写法就是以上写法。
有参装饰器:
(1): #第一步是函数()的效果,第二步是@auth的效果
输出:还他妈的不会玩
#有参函数执行流程
def auth2(auth_type): #1 #3
def auth(func): #4 #6
def wrapper(*args,**kwargs): #7 #10
if auth_type == 'file': #11
name=input('username: ')
password=input('password: ')
if name == 'zhejiangF4' and password == 'sb945':
print('auth successfull')
res=func(*args,**kwargs)
return res
else:
print('auth error')
elif auth_type == 'sql': #12
print('还他妈不会玩') #13
return wrapper #8
return auth #5
@auth2(auth_type='sql') #2
def index():
print('welcome to inex page')
# @auth
# def home():
# print('welcome to home page')
index() #9
多个装饰器:
#多个无参装饰器:
# @aaa
# def func():
# pass
#
# func=aaa(func)
# @ccc
# @bbb
# @aaa
# def func():
# pass
#
# func=ccc(bbb(aaa(func)))
#多个有参装饰器
# @ccc('c')
# @bbb('b')
# @aaa('a')
# def func():
# pass
#
# func=ccc('c')(bbb('b')(aaa('a')(func)))
多个装饰器应用:
import time
current_login={'name':None,'login':False}
def timmer(func):
def wrapper(*args,**kwargs):
start_time=time.time()
res=func(*args,**kwargs) #my_max(1,2)
stop_time=time.time()
print('run time is %s' %(stop_time-start_time))
return res
return wrapper
def auth2(auth_type='file'):
def auth(func):
# print(auth_type)
def wrapper(*args,**kwargs):
if current_login['name'] and current_login['login']:
res=func(*args,**kwargs)
return res
if auth_type == 'file':
name=input('username: ')
password=input('password: ')
if name == 'luchuan' and password == '123':
print('auth successfull')
res=func(*args,**kwargs)
current_login['name']=name
current_login['login']=True
return res
else:
print('auth error')
elif auth_type == 'sql':
print('还他妈不会玩')
return wrapper
return auth
@timmer
@auth2(auth_type='file') #@auth #index=auth(index)
def index():
print('welcome to inex page')
@auth2()
def home():
print('welcome to home page')
#调用阶段
index()
home()
装饰器帮助信息补充:
import time
from functools import wraps
def timmer(func):
@wraps(func)
def wrapper(*args,**kwargs):
'sssssssssssss' # 不加wraps,就会返回'sssssss'帮助信息
start_time=time.time()
func(*args,**kwargs) #home(name)
stop_time=time.time()
print('run time is %s' %(stop_time-start_time))
return wrapper
@timmer
def func(x):
'func test'
print(x)
func(1)
print(func.__doc__) # 查看帮助信息的两种方式
# print(help(func))
#不加wraps,输出sssssssss
#加上wraps,则输出:from test
二 装饰器需要遵循的原则
1.不修改被装饰函数的源代码(开放封闭原则)
2.为被装饰函数添加新功能后,不修改被修饰函数的调用方式
三 实现装饰器知识储备
装饰器=高阶函数+函数嵌套+闭包
装饰器:一个外部函数、一个内部函数、一个return 、如果是有参装饰器,外部再包一层函数。
四 高阶函数
高阶函数定义:
1.函数接收的参数是一个函数名
2.函数的返回值是一个函数名
3.满足上述条件任意一个,都可称之为高阶函数


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) 高阶函数示范


#高阶函数应用1:把函数当做参数传给高阶函数 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),改变了函数的调用方式 把函数当做参数传给高阶函数


#高阶函数应用2:把函数名当做参数传给高阶函数,高阶函数直接返回函数名 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('林海峰')
六 闭包
''' 闭包:在一个作用域里放入定义变量,相当于打了一个包 ''' def father(name): def son(): # name='alex' print('我爸爸是 [%s]' %name) def grandson(): # name='wupeiqi' print('我爷爷是 [%s]' %name) grandson() son() father('林海峰')
七 无参装饰器
无参装饰器=高级函数+函数嵌套
基本框架
1 #这就是一个实现一个装饰器最基本的架子 2 def timer(func): 3 def wrapper(): 4 func() 5 return wrapper
加上参数
1 def timer(func): 2 def wrapper(*args,**kwargs): 3 func(*args,**kwargs) 4 return wrapper
加上功能
1 import time 2 def timer(func): 3 def wrapper(*args,**kwargs): 4 start_time=time.time() 5 func(*args,**kwargs) 6 stop_time=time.time() 7 print('函数[%s],运行时间是[%s]' %(func,stop_time-start_time)) 8 return wrapper
加上返回值
1 import time 2 def timer(func): 3 def wrapper(*args,**kwargs): 4 start_time=time.time() 5 res=func(*args,**kwargs) 6 stop_time=time.time() 7 print('函数[%s],运行时间是[%s]' %(func,stop_time-start_time)) 8 return res 9 return wrapper
使用装饰器
1 def cal(array): 2 res=0 3 for i in array: 4 res+=i 5 return res 6 7 cal=timer(cal) 8 cal(range(10))
语法糖@
1 @timer #@timer就等同于cal=timer(cal) 2 def cal(array): 3 res=0 4 for i in array: 5 res+=i 6 return res 7 8 cal(range(10))
八 装饰器应用示例


user_list=[ {'name':'alex','passwd':'123'}, {'name':'linhaifeng','passwd':'123'}, {'name':'wupeiqi','passwd':'123'}, {'name':'yuanhao','passwd':'123'}, ] current_user={'username':None,'login':False} def auth_deco(func): def wrapper(*args,**kwargs): if current_user['username'] and current_user['login']: res=func(*args,**kwargs) return res username=input('用户名: ').strip() passwd=input('密码: ').strip() for index,user_dic in enumerate(user_list): if username == user_dic['name'] and passwd == user_dic['passwd']: current_user['username']=username current_user['login']=True res=func(*args,**kwargs) return res break else: print('用户名或者密码错误,重新登录') return wrapper @auth_deco def index(): print('欢迎来到主页面') @auth_deco def home(): print('这里是你家') def shopping_car(): print('查看购物车啊亲') def order(): print('查看订单啊亲') print(user_list) # index() print(user_list) home() 无参装饰器


user_list=[ {'name':'alex','passwd':'123'}, {'name':'linhaifeng','passwd':'123'}, {'name':'wupeiqi','passwd':'123'}, {'name':'yuanhao','passwd':'123'}, ] current_user={'username':None,'login':False} def auth(auth_type='file'): def auth_deco(func): def wrapper(*args,**kwargs): if auth_type == 'file': if current_user['username'] and current_user['login']: res=func(*args,**kwargs) return res username=input('用户名: ').strip() passwd=input('密码: ').strip() for index,user_dic in enumerate(user_list): if username == user_dic['name'] and passwd == user_dic['passwd']: current_user['username']=username current_user['login']=True res=func(*args,**kwargs) return res break else: print('用户名或者密码错误,重新登录') elif auth_type == 'ldap': print('巴拉巴拉小魔仙') res=func(*args,**kwargs) return res return wrapper return auth_deco #auth(auth_type='file')就是在运行一个函数,然后返回auth_deco,所以@auth(auth_type='file') #就相当于@auth_deco,只不过现在,我们的auth_deco作为一个闭包的应用,外层的包auth给它留了一个auth_type='file'参数 @auth(auth_type='ldap') def index(): print('欢迎来到主页面') @auth(auth_type='ldap') def home(): print('这里是你家') def shopping_car(): print('查看购物车啊亲') def order(): print('查看订单啊亲') # print(user_list) index() # print(user_list) home() 带参装饰器
参考链接:http://www.cnblogs.com/linhaifeng/articles/6140395.html
参考链接:http://www.cnblogs.com/yuanchenqi/articles/5828233.html#3503895