python装饰器
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python装饰器相关的知识,希望对你有一定的参考价值。
装饰器:
定义:
装饰器 本质是函数; 器代表函数;
功能:
装饰其他函数,就是为其他函数添加附加功能;
原则:
1.不能修改被装饰的函数的源代码
2.不能修改被装饰的函数的调用方式
装饰器对被装饰的函数是透明的。感受不到装饰器的存在。
实现装饰器知识储备:
1.函数即“变量”
一个简单的装饰器例子
import time 定义装饰器 def timmer(func): def warrper(*args,**kwargs): start_time=time.time() func() stop_time=time.time() print("the func run time is %s"%(stop_time-start_time)) return warrper @timmer def test1(): time.sleep(3) print("in the test1") test1()
举例说明:
def foo(): print("in the foo") bar() foo() 报错bar没有定义
def bar(): print("in the bar") def foo(): print("in the foo") bar() foo() 正常运行
def foo(): print("in the foo") bar() def bar(): print("in the bar") foo() 正常运行
运行该例子的时候,先将定义的函数foo、bar依次存储到了内存;
然后在运行foo(),调用bar是在内存中存在的,所以不会报错。
def foo(): print("in the foo") bar() foo() def bar(): print("in the bar") foo() 会报错提示bar没有定义
执行foo(),先将foo函数存储到内存,然后就运行foo;
而此时bar函数还没有定义写到内存中,找不到bar所以会报错。
总结:
定义一个函数就相当于将函数体赋值给函数名;
定义变量/函数 是先定义,再执行;
函数和变量一样都会被python内存回收机制回收;
所以:函数即“变量”
1.1匿名函数
#函数没有名字,下面给函数定义了一个变量名来引用;
niming = lambda x:x*3 print (niming(3))
2.高阶函数
a:把一个函数名当做实参给另外一个函数;
(在不修改被装饰函数源代码的情况下为其添加功能)
b:返回值中包含函数名;
(不修改函数的调用方式)
把函数当作一个实参传递给形参。
简单例子
def bar(): print("in the bar") def test1(func): print(func) func() test1(bar) func()等于下面 func=bar func()
稍作改变
def bar(): time.sleep(0.3) print("in the bar") def test1(func): start_time=time.time() func() stop_time=time.time() print("the func run time is %s" %(stop_time-start_time)) test1(bar)
总结:(在不修改被装饰函数源代码的情况下为其添加功能)
def bar(): time.sleep(0.3) print("in the bar") def test2(func): print(func) return func 运行1 print(test2(bar)) 运行2 t = test2(bar) t() #运行3 bar=test2(bar) bar() bar是原函数
总结:返回值中包含函数名; (不修改函数的调用方式)
写一个装饰器(高阶函数)
import time def deco(func): star_time= time.time() func() stop_time=time.time() print("th func run time is %s"%(stop_time-star_time)) def deco(func): star_time= time.time() return func stop_time=time.time() print("th func run time is %s"%(stop_time-star_time)) def test1(): time.sleep(3) print("in the test1") def test2(): time.sleep(3) print("in the test2") deco(test1) deco(test2) test1=deco(test1) test1() test2=deco(test2) test2() 结束时间没有运行;
3.嵌套函数
高阶函数+嵌套函数= 装饰器
变化1
def timmer(func): def deco(): star_time= time.time() func() stop_time=time.time() print("th func run time is %s"%(stop_time-star_time)) return deco def test1(): time.sleep(3) print("in the test1") def test2(): time.sleep(3) print("in the test2") test1=timmer(test1) test1() test2=timmer(test2) test2()
变化2 应用装饰器 嵌套函数
def timmer(func): def deco(): star_time= time.time() func() stop_time=time.time() print("th func run time is %s"%(stop_time-star_time)) return deco @timmer #@timmer 就等于test1=timmer(test1) ;这就是装饰器 def test1(): time.sleep(3) print("in the test1") @timmer def test2(): time.sleep(3) print("in the test2") test1() test2()
变化3 高级装饰器 可以满足日常90%的需求
def timmer(func): def deco(*args,**kwargs): star_time= time.time() func(*args,**kwargs) stop_time=time.time() print("th func run time is %s"%(stop_time-star_time)) return deco @timmer #@timmer 就等于test1=timmer(test1) ;这就是装饰器 def test1(): time.sleep(3) print("in the test1") @timmer def test2(name,age): time.sleep(3) print("in the test2:name age") test1() test2("abc",123)
终极高级版 decorator 就是装饰器的意思;
一、默认谁都可以访问三个网站
def index(): print("welcome to index page") def home(): print("welcome to home page") def bbs(): print("welcome to bbs page") index() home() bbs()
二、一部分home/bbs需要登录才能浏览
user,passwd="abc","123" def auth(func): def wrapper(*args,**kwargs): username = input("Username:").strip() password = input("Password:").strip() if user == username and passwd == password: print("\033[32;1m Auth is sucessed!\033[0m") func(*args,**kwargs) else: print("\033[31;1m Auth is failed!\033[0m") return wrapper def index(): print("welcome to index page") @auth def home(): print("welcome to home page") @auth def bbs(): print("welcome to bbs page") index() home() bbs()
三、一部分home/bbs需要登录才能浏览
user,passwd="abc","123" def auth(func): def wrapper(*args,**kwargs): username = input("Username:").strip() password = input("Password:").strip() if user == username and passwd == password: print("\033[32;1m Auth is sucessed!\033[0m") ret = func(*args,**kwargs) #from home ; 也可以直接return print("-----after auth ") return ret else: print("\033[31;1m Auth is failed!\033[0m") return wrapper #而这里没有返回值;在上边return ret之后就有数据了 def index(): print("welcome to index page") @auth #当home有return结果的时候,用上边的无法获取到home return的结果;wrapper加一个return; def home(): print("welcome to home page") return "From home!" @auth def bbs(): print("welcome to bbs page") index() print(home()) #调用home相当于调用wrapper bbs()
四、home bbs两个目录,一部分可以直接访问,一部分需要登录才能浏览
以上案例是验证写死的,运维中有本地认证和ldap认证,认证方式有多种,需要以下完成;
home用本地认证,bbs用远程ldap认证;
import time user,passwd="abc","123" def auth(auth_type): print(auth_type) def outer_wrapper(func): def wrapper(*args,**kwargs): print("--wrapper func args:",*args,**kwargs) if auth_type == "local": username = input("Username:").strip() password = input("Password:").strip() if user == username and passwd == password: print("\033[32;1m Auth is sucessed!\033[0m") ret = func(*args, **kwargs) # from home,就是去运行home ; 也可以直接return print("-----after auth ") return ret else: print("\033[31;1m Auth is failed!\033[0m") elif auth_type == "ldap": print("no no no ldap!") return wrapper # 而这里没有返回值;在上边return ret之后就有数据了 return outer_wrapper def index(): print("welcome to index page") #当home有return结果的时候,用上边的无法获取到home return的结果;wrapper加一个return; @auth(auth_type="local") #home = auth() def home(): print("welcome to home page") return "From home!" @auth(auth_type="ldap") def bbs(): print("welcome to bbs page") index() print(home()) #调用home相当于调用wrapper bbs()
本文出自 “506554897” 博客,请务必保留此出处http://506554897.blog.51cto.com/2823970/1963710
以上是关于python装饰器的主要内容,如果未能解决你的问题,请参考以下文章