Python-无参装饰器1-需求案例

需求:在不修改index函数(被装饰对象)的源代码以及调用方式的前提下为其添加统计运行时间的功能
def index(x,y):
   time.sleep(3)
   print("hahaha%s %s"%(x,y))

index(111,222)
# index(x=111,y=222)
# index(111,y=222)

解决方案一:失败
问题:没有修改被装饰对象的调用方式,但是修改了其源代码
import time
def index(x,y):
start_time=time.time()
time.sleep(3)
print("hahaha%s %s"%(x,y))
stop_time = time.time()
print(stop_time-start_time)


index(111,222)

解决方案二:
问题:没有修改被装饰对象的调用方式,也没有修改其源代码。并且也加上了新功能但是代码冗余
import time
def index(x,y):
time.sleep(3)
print("hahaha%s %s"%(x,y))

start_time=time.time()
index(111,222) #调用index函数就是执行函数体中的这两行源代码
stop_time = time.time()
print(stop_time-start_time)

如果这个index函数有多处调用
start_time=time.time()
index(111,222) #调用index函数就是执行函数体中的这两行源代码
stop_time = time.time()
print(stop_time-start_time)

start_time=time.time()
index(111,222) #调用index函数就是执行函数体中的这两行源代码
stop_time = time.time()
print(stop_time-start_time)


解决方案三:失败
问题:解决了方案二代码的冗余问题,但带来一个新问题即函数的调用方式被改变了
import time
def index(x,y):
time.sleep(3)
print("hahaha%s %s"%(x,y))

#遇到重复的代码定义函数
def wrapper():
start_time=time.time()
index(111,222) #调用index函数就是执行函数体中的这两行源代码
stop_time = time.time()
print(stop_time-start_time)

wrapper()

方案三的优化:
import time
def index(x,y):
time.sleep(3)
print("hahaha%s %s"%(x,y))

#遇到重复的代码定义函数
def wrapper(a,b): #a=111,b=222
start_time=time.time()
#index(111,222) #index函数中的参数写死了,使用变量的方式
index(a,b) #index属于wrapper内的,index需要的就是wrapper需要. index(111,222)
stop_time = time.time()
print(stop_time-start_time)

wrapper(111,222) #wrapper(333,444) 参数传参就写活了

以后index这个功能需要变化,如index(x,y,z),那么wrapper也需要跟着改
import time
def index(x,y,z):
time.sleep(3)
print("hahaha%s %s %s"%(x,y,z))

def wrapper(a,b,c):
start_time=time.time()
index(a,b,c)
stop_time = time.time()
print(stop_time-start_time)

wrapper(111,222,333)



方案三的优化一:将被装饰对象index参数写活了
#针对index功能以后需要变化,将被装饰对象参数写活
import time
def index(x,y,z):
time.sleep(3)
print("hahaha%s %s %s"%(x,y,z))

def wrapper(*args,**kwargs):
start_time=time.time()
index(*args,**kwargs) #index(111,222,333) 为wrapper传参会原封不动的转接给index(111,222,333)
stop_time = time.time()
print(stop_time-start_time)

wrapper(111,222,333) #为wrapper传参会原封不动的转接给index(111,222,333),为wrapper传参需要遵循index函数的参数。


方案三的优化二:在优化一的基础上把被装饰对象index写死了,原来只能装饰index
import time
def index(x,y,z):
time.sleep(3)
print("hahaha%s %s %s"%(x,y,z))
print("原来的index的内存地址",index)

#如果我再有一个home函数,那还得在继续写一个home的装饰器,这样就出现了代码的冗余了
def home(name):
time.sleep(3)
print("hahaha%s" %name)

#函数体为了把被装饰对象写活,将被装饰对象固定写死的index,定义成变量。遇到问题函数体需要一个参数传进来
传参的两种方式:
实参形参方式:不满足,为wrapper传参会原封不动的转接给index(111,222,333),为wrapper传参需要遵循index函数的参数。
闭包函数:满足,只能通过闭包函数传参。

'''
def outter(func):
#func=index 写死了,要写活,放到outter形参中
def wrapper(*args,**kwargs) 将这个函数合起来
return wrapper 为什么返回wrapper,因为wrapper当初属于全局的,为了给wrapper函数体内包一个所需的参数
将wrapper缩进到一个函数内。还想在全局使用wrapper就的return wrapper

怎么拿到wrapper
f=outter() f=当初那个wrapper函数的内存地址
'''


def outter(func):
#func=index的内存地址
def wrapper(*args,**kwargs):
start_time=time.time()
#index的内存地址()
func(*args,**kwargs) #函数体为了把被装饰对象写活,将被装饰对象固定写死的index,定义成变量。遇到问题函数体需要一个参数传进来
stop_time = time.time()
print(stop_time-start_time)
return wrapper


f=outter(index) #f=outter(index的内存地址)

f(1,y=2,z=3) #调用f()是调用wrapper(),为wrapper(1,y=2,z=3)传参就是为其index传参
#上面虽然没有修改index函数的源代码但是改变了index函数的调用方式

index=outter(index) #可以赋值给任意变量,现在赋值给index变量
index(11,y=22,z=33) #index=wrapper的内存地址
#上面虽然没有修改被装饰对象index函数的源代码及调用方式也为其增加了新功能,但是现在的这个index已经不是原来的那个index了,已经被偷梁换柱了(打印内存地址),

home=outter(home) #home=wrapper的内存地址
home('llj')


方案三的优化三:将wrapper做的跟被装饰对象一模一样,以假乱真,以下就是修改的步骤
import time
def home(name):
time.sleep(3)
print("hahaha%s" %name)
return 123 #如果函数有返回值呢


def outter(func):
#func=home
def wrapper(*args,**kwargs):
start_time=time.time()
time.sleep(3)
res=func(*args,**kwargs) #这儿的func(*args,**kwargs)就是home(*args,**kwargs),调用的是home(),所以能拿到返回值
stop_time=time.time()
print(stop_time-start_time)
#return 123 #这样写返回值就写死了
return res #伪装home()返回啥,wrapper()就返回啥
return wrapper

#偷梁换柱:home这个名字指向的wrapper函数的内存地址
home=outter(home)
res=home('llj') #其实调用的是wrapper(),res=wrapper('llj')
print("返回值--》",res) #原home()函数有返回值,wrapper()函数就返回啥
 
 
 
 
 
 
 
 



 


 
posted @ 2020-11-09 10:33  梁博客  阅读(74)  评论(0)    收藏  举报