引入装饰器的思想:
如果我们想为某一个功能添加一个新的功能,如何在不改变他的原来的函数名的情况下实现呢?
我们可能会这样:
1.直接在原来的函数里头添加功能模块 --- 代码量太大逐一添加不太现实
2.再写一个新的函数,在原来的函数里分别调用 --- 如果原来的函数在多处调用,且太过分散,工程量太大
3.定义一个新的函数:
def cover():
newFunc()
oldFunc()
在新函数里头注入一个参数为 -- 原来的函数(函数作为参数传入)
def cover(oldFunc) -- 此处不能有括号否则为调用函数
newFunc()
oldFunc()
cover(oldFunc) -- 调用
那么这样又违背了题意 --- 显然不合格
上述的三种方法都不能实现,那么装饰器的思想应运而生
即在第三种方法的理念下,既添加了新功能,有没有修改名字
def covered(func):
def cover():
newFunc()
oldFunc()
return cover
即: cover = covered(oldFunc)
cover() ">=" oldFunc()
调用oldFunc 就可以写作调用cover()
cover()函数是oldFunc()函数的增强版
实现换皮不换肉,还变肥的操作
我们重新归纳:
def newFunc():
print("需要添加的新功能")
def outter(fun):
def inner(name):
newFunc()
return fun(name)
return inner
# 在一个函数上加上@,表示使用装饰器,@符号后跟的是 装饰器的函数名
# 如: @outter 相当于执行了 func = outter(func) ---> 将inner修改成原函数名 = 装饰器函数名(需要添加新功能的原函数名)
@outter
def func(name):
print("%s的基础功能"%name)
return name
print(func("胖胖")) #inner("胖胖") 注意此处的func与原来的并不是一样的,而是改装后名字一样而已
这就是装饰器的基本思想,那么如何实现一个通用的装饰器呢?即实现一个通用的装饰器,起始也很简单只需要在传参上修改就行:
[python] view plain copy
def newFunc():
print("需要添加的新功能")
def outter(fun):
def inner(*args,**kwargs):
newFunc()# 如果有必要,可以在新功能出也添加
return fun(*args,**kwargs)
return inner
@outter
def func(name,food):
print("%s的基础功能是吃%s"%(name,food))
return name
print(func("小贱贱","面包")) #<==> print(inner("小贱贱","面包"))
我们来看看具体应用:
一.创建一个装饰器把下面函数输出的字符串首字母大写
# 思路: 使用装饰器,装饰器可以给原函数重新命名,添加新的功能
# 可以在装饰器里给新旧函数排序使得旧函数有新的功能
# def geeting(word="hi there"):
# return word.lower()
[python] view plain copy
#解答:
def newGeeting(word):
return word.capitalize()
def change(geet):
def geetings(**kwargs):
geet(**kwargs)
return newGeeting(**kwargs)
return geetings
@change
def geeting(word="hi there"):
return word.lower()
print(geeting(word="hi there"))
二.使用一个装饰器,查看函数运行时间
# 思路:运行时间 导入时间模块,在装饰器内部 函数前后分别获取当前时间戳,函数运行结束后,差值就是函数运行时间
[python] view plain copy
#解答:
import time
def time1(func):
def newFunc():
startTime = time.time()
func()
endTime = time.time()
return endTime-startTime
return newFunc
@time1
def oldFunc():
time.sleep(2)
print("我正在运行中")
print(oldFunc())
那么装饰器就说到这里,你是否有所收获呢?
网友评论