ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

python基础语法学习: 装饰器

python基础语法学习: 装饰器 文章目录装饰器装饰器的一般写法 (闭包写法)装饰器的语法糖写法装饰器带参数装饰器之原函数带返回值一个函数可以被多个装饰器装饰通用装饰器的写法:装饰器装饰器本质上是一种闭包, 其功能就是在不破坏目标函数原有的代码和功能的前提下,为目标函数增加新功能.函数拥有一下特点:函数可以作为参数进行传递函数可以作为返回值进行返回函数名称可以当成变量一样进行赋值操作现在有一个 sleep 函数defsleep():importrandomimporttimeprint(sleeping)time.sleep(random.randint(1,5))现在希望给 sleep 函数增加一个新功能:在调用 sleep 前输出:I will sleep在调用 sleep 后输出:I wake有下面的代码:print(I will sleep)sleep()print(I wake)但是这样的方式非常的不优雅,那有没有其他方式呢, 有的, 可以使用 装饰器来实现装饰器的一般写法 (闭包写法)defsleep():importrandomimporttimeprint(sleeping)time.sleep(random.randint(1,5))defouter(func):definner():print(I will sleep)func()print(I wake)returninner fnouter(sleep)fn()装饰器的语法糖写法defouter(func):definner():print(I will sleep)func()print(I wake)returninnerouterdefsleep():importrandomimporttimeprint(sleeping ...)time.sleep(random.randint(1,5))sleep()使用outer, 定义在目标函数之上这种写法与装饰器的一般写法的调用方式以一样的, 这里调用sleep(), 本质上调用的还是inner()装饰器带参数先给出无参形式的代码defouter(func):definner():print(start)func()print(end)returninnerouterdefsleep(time):print(sleeping)sleep()现在要给上述的sleep函数添加一个参数defsleep(time):print(fsleeping, time:{time})那么再按照原来的方式调用就会报错defouter(func):definner():print(start)func()print(end)returninnerouterdefsleep(time):print(fsleeping, time:{time})sleep(45)上述代码中outer等价于sleep outer(sleep), 实际上就是调用inner()当outer装饰sleep函数时outer(sleep)返回的是inner函数而inner没有参数导致调用sleep()时无法传递time参数。解决方法: 在inner函数中添加*args, **kwargs来接收任意参数并传递给funcdefouter(func):definner(*args,**kwargs):print(start)func(*args,**kwargs)print(end)returninnerouterdefsleep(time):print(fsleeping, time:{time})sleep(32)输出:start sleeping,time:32end装饰器之原函数带返回值下面要演示原函数带返回值下面函数返回值并且要打印返回值defsleep(time):print(fsleeping, time:{time})returnwakeprint(sleep(1))# wake那么现在要给这个函数添加一个装饰器只需要在装饰器内部用一个变量接收返回值并且内部的inner()返回这个返回值即可defouter(func):definner(*args,**kwargs):print(start)retfunc(*args,**kwargs)print(end)returnretreturninnerouterdefsleep(time):print(fsleeping, time:{time})returnwakeprint(sleep(1))一个函数可以被多个装饰器装饰defwrapper1(func):definner(*args,**kwargs):print(in wrapper1)func(*args,**kwargs)print(out wrapper1)returninnerdefwrapper2(func):definner(*args,**kwargs):print(in wrapper2)func(*args,**kwargs)print(out wrapper2)returninnerwrapper1wrapper2deftarget():print(in target)target()打印:inwrapper1inwrapper2intarget out wrapper2 out wrapper1装饰器的执行顺序是从下往上wrapper1wrapper2deftarget():print(in target)等价于target wrapper1(wrapper2(target))执行步骤装饰阶段定义时wrapper2先执行target wrapper2(target)→target变成wrapper2的innerwrapper1后执行target wrapper1(已装饰的target)→target变成wrapper1的inner调用阶段target()时wrapper1.inner() 开始 ├── 打印 in wrapper1 ├── 调用 func() → 这个 func 是 wrapper2.inner() │ ├── 打印 in wrapper2 │ ├── 调用 func() → 这个 func 是原始的 target() │ │ └── 打印 in target │ └── 打印 out wrapper2 └── 打印 out wrapper1通用装饰器的写法:defwrapper(fn):defwrapper(*args,**kwargs):# 目标函数执行之前 ...retfn(*args,**kwargs)# 目标函数执行之后 ...returnretreturnwrapper# 不加()wrapperdeftarget(*args,**kwargs):pass这里添加装饰器之后再调用目标函数target(), 实际上就是调用inner()
返回列表