python类装饰器应用_python开发装饰器的应用

一、 装饰器

装饰器就是闭包函数的一种应用场景

什么是闭包函数?我们再来回忆一下:

闭包函数:

定义在函数内部的函数,并且该函数包含对外部函数作用域(强调:对全局作用域名字的引用不算闭包)名字的引用,该函数称为闭包函数

说到作用域我们再回忆下:

作用域:

全局范围:内置+全局

全局有效,全局存活

局部范围:局部

局部有效,局部存活

作用域关系是在函数定义阶段就规定死,与调用位置无关,

也就是说,无论函数在哪儿调用,都必须回到当初定义函数时的位置找作用域关系

一 、为何要用装饰器

#开放封闭原则:

#软件一旦上线后,就应该遵循开放封闭原则,对修改源代码是封闭的,对功能的扩展是开放的,也就是我们必须找到一种解决方法:

#能够在不修改一个功能源代码以及调用方式的前提下,为其加上新功能.

二 、什么是装饰器

#装饰器他人的器具,本身可以是任意可调用对象,被装饰者也可以是任意可调用对象。

#强调装饰器的原则:

#1 、不修改被装饰对象的源代码

#2 、不修改被装饰对象的调用方式

#装饰器的目标:

#在遵循1和2的前提下,为被装饰对象添加上新功能

三 、装饰器的使用

78d0544535c4ec201468987e6c3dab09.png

#我们现在给下面函数增加一个运行时间的功能

import time

def index():

time.sleep(3)

print('welcome to index page')

#修改一

def index():

start_time=time.time()

time.sleep(3)

print('welcome to index page')

stop_time=time.time()

print('run time is %s' %(stop_time-start_time))

index() #功能实现

#评语:直接改源代码,这么搞被开了。。。

78d0544535c4ec201468987e6c3dab09.png

78d0544535c4ec201468987e6c3dab09.png

#再来一位童靴,来实现功能

#修改二

import time

def index():

time.sleep(1)

print('welcome to index page')

start_time=time.time()

index()

stop_time = time.time()

print('run time is %s' % (stop_time - start_time))

#评语:有好多函数要实现这个功能,写N遍变这个代码,

#后期维护一脸懵逼,还是被开。。。

78d0544535c4ec201468987e6c3dab09.png

78d0544535c4ec201468987e6c3dab09.png

#再来一位童靴,功能重复实现看我用强大的函数

#修订三:

import time

def index():

time.sleep(3)

print('welcome to index page')

def wrapper(func): #func=index

start_time=time.time()

func() #index()

stop_time = time.time()

print('run time is %s' % (stop_time - start_time))

wrapper(index)

#评语:修改了原函数的调用方式,依然被开。。。

78d0544535c4ec201468987e6c3dab09.png

78d0544535c4ec201468987e6c3dab09.png

#终于来了位小牛的童靴,函数的值可以返回,然后我再把重新定义index

#修订四:

import time

def index():

time.sleep(3)

print('welcome to index page')

def outter(func): #func=最原始的index

# func=最原始的index

def wrapper():

start_time=time.time()

func()

stop_time=time.time()

print(stop_time-start_time)

return wrapper

index=outter(index) # 新的index=wrapper

index() #wrapper() 功能基本实现

#评语:在原值没有返回值是没问题,但是有返回值的情况下,这么搞就会发现返回的是None

78d0544535c4ec201468987e6c3dab09.png

78d0544535c4ec201468987e6c3dab09.png

#这次小牛牛童靴路过看到这情况,say这么搞!

#修订五

import time

def index():

time.sleep(1)

print('welcome to index page')

return 123 #假使这里返回123 返回值可以是任意类型

#==============下面就是装饰器

def timmer(func):

#func=最原始的index

def wrapper(*args,**kwargs): #可变长参数

start_time=time.time()

res=func(*args,**kwargs) #调用最原始的index

stop_time=time.time()

print(stop_time-start_time)

return res #index()运行的返回值

return wrapper

index=timmer(index) # 新的index=wrapper

print(index()) #功能已经实现,返回值123

#评语:这里的装饰的功能已经实现,返回的值也得到,小牛牛不是白叫的

78d0544535c4ec201468987e6c3dab09.png

78d0544535c4ec201468987e6c3dab09.png

#天上五彩红光,大牛童靴出现!各位童靴火速围观!

import time

def timmer(func):

def wrapper(*args,**kwargs):

start_time=time.time()

res=func(*args,**kwargs)

stop_time=time.time()

print(stop_time-start_time)

return res

return wrapper

@timmer #index=timmer(index) 装饰器的标准格式!

def index():

time.sleep(1)

print('welcome to index page')

return 123

@timmer # home=timmer(home)

def home(name):

time.sleep(2)

print('welcome %s to home page' %name)

# index()

#home('egon')

#评语:大牛就是大牛!大牛say:教你们绝技,不会的童靴可以照下面的模板实现:

#无参装饰器模板

def outer(func): #outer,inner名字功能随意

def inner(*args,**kwargs):

res=func(*args,**kwargs)

return res

return inner

@outer #装饰器要在装饰函数的上方

def duoduo():

pass

78d0544535c4ec201468987e6c3dab09.png

四 、装饰器语法

78d0544535c4ec201468987e6c3dab09.png

#被装饰函数的正上方,单独一行

@deco1

@deco2

@deco3

def foo():

pass

#foo=deco1(deco2(deco3(foo)))

#这里的思想就是最上面装饰器,装饰的下面所有的函数(deco2,deco3,foo)

#然后deco2装饰(deco3,foo),最后deco3装饰foo

#功能的不同,放的顺序也要注意,不然装饰的效果可能实现的就不对了!

78d0544535c4ec201468987e6c3dab09.png

五、多个装饰器的使用:

78d0544535c4ec201468987e6c3dab09.png

import time

current_user={

'username':None,

# 'login_time':None

}

def auth(func):

# func=index

def wrapper(*args,**kwargs):

if current_user['username']: #这里是认证过的,下次就不用认证

print('已经登陆过了')

res=func(*args,**kwargs)

return res

uname=input('用户名>>: ').strip()

pwd=input('密码>>: ').strip()

if uname == 'egon' and pwd == '123':

print('登陆成功')

current_user['username']=uname

res=func(*args,**kwargs)

return res

else:

print('用户名或密码错误')

return wrapper

def timmer(func):

def wrapper(*args,**kwargs):

start_time=time.time()

res=func(*args,**kwargs)

stop_time=time.time()

print(stop_time-start_time)

return res

return wrapper

@timmer # timmer 统计的是auth+index的执行时间

@auth #我们只装饰index的话就要把@timmer紧跟index

def index():

time.sleep(1)

print('welcome to index page')

return 123

@auth

@timmer #这里统计的就是home运行的时间

def home(name):

time.sleep(2)

print('welcome %s to home page' %name)

#index()

#home("duoduo")

78d0544535c4ec201468987e6c3dab09.png

六、有参数的装饰器的使用:

78d0544535c4ec201468987e6c3dab09.png

import time

current_user={

'username':None,

# 'login_time':None

}

def auth(engine): #道理还是那个道理,在外面包了一层engine的值

# engine='file' #这个值外面穿什么进来就是什么

def auth2(func):

# func=index

def wrapper(*args,**kwargs):

if engine == 'file':

if current_user['username']:

print('已经登陆过了')

res=func(*args,**kwargs)

return res

uname=input('用户名>>: ').strip()

pwd=input('密码>>: ').strip()

if uname == 'egon' and pwd == '123':

print('登陆成功')

current_user['username']=uname

res=func(*args,**kwargs)

return res

else:

print('用户名或密码错误')

elif engine == 'mysql': #engine 值得判断情况

print('基于MyQL的认证')

elif engine == 'ldap':

print('基于LDAP的认证')

return wrapper

return auth2 #这里也要返回auth2的内存地址

@auth('ldap') #@auth2 #index=auth2(index) #index=wrapper

def index():

time.sleep(1)

print('welcome to index page')

return 123

index() # wrapper()

78d0544535c4ec201468987e6c3dab09.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值