博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python 如何理解又晕又好用的装饰器
阅读量:6309 次
发布时间:2019-06-22

本文共 3850 字,大约阅读时间需要 12 分钟。

Python 装饰器这东西对初学者来说是个坑,很容易绕晕,笔者当时初学装饰器时花费了数天时间,看了不同讲师对这块内容的讲解,还是一知半解。  

 不过装饰器在开发中可是很好用的,有必要攻破,希望这篇文章能帮助学习者快速攻破难关。

初步理解

# 先来看一个简单函数def show():    print ('Mr tu')show()# 执行结果 :Mr tu# 现在我们用装饰器扩展这个函数,在打印 " Mr tu " 之前打印一行 " hello "  def decorate(fun1):    def wapper():        print('hello')        fun1()    return wapper@decoratedef show():    print ('Mr tu')show()# 执行结果 :helloMr tu# 现在解释上面的代码。# 1、首先 def decorate(fun1) 定义一个装饰器函数,在此函数里又定义了一个wapper子函数,子函数可以继承父函数的参数。# 2、 @'函数名'是Python的一种语法糖 @decorate 等于 decorate(show) # 还是晕,不明白?  没关系,看下面代码:def decorate(fun1):    def wapper():        print('hello')        fun1()    return wapperdef show():    print ('Mr tu')f1 = decorate(show)f1()# 执行结果 :helloMr tu# 换成这种写法,执行效果是一样的,因为这就是 @decorate 的本质。# 就是将被装饰器装饰的函数show作为参数传给装饰器函数。# 总结执行过程:# 1、show函数作为参数传给装饰器函数 decorate ,那么 fun1 = show# 2、这时执行到装饰器的子函数 wapper,子函数可以继承父函数的参数,所以可以调用 fun1 # 3、然后wapper函数执行 print 打印一行 "hello" , 再然后  调用fun1() —— 这里其实就是执行了show函数。  因为在装饰器一开始执行的时候就把show函数作为参数赋值给了fun1.# 现在明白了吧,只要这里明白,下面的就很好理解了。

装饰带参数的函数

# 一个参数def decorate(fun1):    def wapper(arg1):        print('hello')        fun1(arg1)        print('nice to meet you')    return wapper@decoratedef show(arg1):    print (arg1)    show('Mr Alice')# 执行结果:helloMr Alicenice to meet you# 两个参数def decorate(fun1):    def wapper(arg1,arg2):        print('hello')        fun1(arg1,arg2)        print('nice to meet you')    return wapper@decoratedef show(arg1,arg2):    print (arg1,arg2)show('Mr Alice','Mr Tom')# 执行结果:hello('Mr Alice', 'Mr Tom')nice to meet you# n个参数def decorate(fun1):    def wapper(*args,**kwargs):        print('hello')        fun1(*args,**kwargs)        print('nice to meet you')    return wapper@decoratedef show(*args,**kwargs):    print (args[0])    print (args[1])    print (args[2])show('Mr Alice','Mr Tim','Mr tu')# 执行结果:helloMr AliceMr TimMr tunice to meet you

一个函数被多个装饰器装饰

def decorate01(fun1):    def wapper(*args,**kwargs):        print('hello world')        print('I am decorate01')        fun1(*args,**kwargs)    return wapperdef decorate02(fun1):    def wapper(*args,**kwargs):        print ('I am decorate02')        fun1(*args,**kwargs)        print('nice to meet you')    return wapper@decorate01@decorate02def show(*args,**kwargs):    print (args[0])    print (args[1])    print (args[2])show('Mr Alice','Mr Tim','Mr tu')# 执行结果:hello worldI am decorate01I am decorate02Mr AliceMr TimMr tunice to meet you# 观察print放置的位置不同,对应的输出结果不同。def decorate01(fun1):    def wapper(*args,**kwargs):        print('hello world')        fun1(*args,**kwargs)        print('I am decorate01')  # 替换到了下面    return wapperdef decorate02(fun1):    def wapper(*args,**kwargs):        print ('I am decorate02')        fun1(*args,**kwargs)        print('nice to meet you')    return wapper@decorate01@decorate02def show(*args,**kwargs):    print (args[0])    print (args[1])    print (args[2])show('Mr Alice','Mr Tim','Mr tu')# 执行结果:hello worldI am decorate02Mr AliceMr TimMr tunice to meet youI am decorate01

装饰器功能扩展

#!/usr/local/python27/bin/python2.7def before(request,*args,**kwargs):    print('before')def after(request,*args,**kwargs):    print('after')def Filter(before_func,after_func):    def outer(fun1):        def wapper(request,*args,**kwargs):            before_result = before_func(request,*args,**kwargs)            if(before_result != None):                return before_result;            fun1_result = fun1(request,*args,**kwargs)            if(fun1_result != None):                return fun1_result;            after_result = after_func(request,*args,**kwargs)            if(after_result != None):                return after_result;        return wapper    return outer@Filter(before,after)def show(request,*args,**kwargs):    print ('Mr tu')    show('1')# 执行结果:beforeMr tuafter

函数若未定义返回值,执行成功返回值默认为 None ,这里的语句 if (before_result != None) 意思就是before函数执行失败时采取什么操作。

转载地址:http://wfxxa.baihongyu.com/

你可能感兴趣的文章
公司内部分享【富有成效的每日站会】总结
查看>>
打造一个上传图片到图床利器的插件(Mac版 开源)
查看>>
iOS横竖屏
查看>>
thinkphp判断更新是否成功
查看>>
Do While ... Loop 与 Do Until ... Loop 的区别
查看>>
【Linux】查询某个字符串出现次数
查看>>
高效使用jquery之一:请使用'On'函数
查看>>
冲刺第一周第三天
查看>>
ERP环境检测工具设计与实现 Environment Detection
查看>>
不要在构造中做太多事情,不然有时候会出现有意思的代码~
查看>>
IIS 发布网站遇到的问题
查看>>
NuGet学习笔记(2)——使用图形化界面打包自己的类库
查看>>
xcode中没有autoSizing的设置
查看>>
字符编码
查看>>
企业应用:应用层查询接口设计
查看>>
浅谈Excel开发:十 Excel 开发中与线程相关的若干问题
查看>>
nfd指令的详细说明
查看>>
安装VisualSvn Server时遇到的问题
查看>>
不用Visual Studio,5分钟轻松实现一张报表
查看>>
人脸识别 开放书籍 下载地址
查看>>