Python 如何理解又晕又好用的装饰器

Python 如何理解又晕又好用的装饰器

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


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


初步理解

# 先来看一个简单函数

def show():
    print ('Mr tu')

show()

# 执行结果 :

Mr tu


# 现在我们用装饰器扩展这个函数,在打印 " Mr tu " 之前打印一行 " hello "  


def decorate(fun1):
    def wapper():
        print('hello')
        fun1()
    return wapper


@decorate
def show():
    print ('Mr tu')

show()


# 执行结果 :

hello
Mr tu


# 现在解释上面的代码。

# 1、首先 def decorate(fun1) 定义一个装饰器函数,在此函数里又定义了一个wapper子函数,子函数可以继承父函数的参数。

# 2、 @'函数名'是Python的一种语法糖 @decorate 等于 decorate(show) 

# 还是晕,不明白?  没关系,看下面代码:


def decorate(fun1):
    def wapper():
        print('hello')
        fun1()
    return wapper


def show():
    print ('Mr tu')

f1 = decorate(show)
f1()

# 执行结果 :

hello
Mr 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

@decorate
def show(arg1):
    print (arg1)

    
show('Mr Alice')

# 执行结果:

hello
Mr Alice
nice to meet you


# 两个参数

def decorate(fun1):
    def wapper(arg1,arg2):
        print('hello')
        fun1(arg1,arg2)
        print('nice to meet you')
    return wapper

@decorate
def 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

@decorate
def show(*args,**kwargs):
    print (args[0])
    print (args[1])
    print (args[2])


show('Mr Alice','Mr Tim','Mr tu')


# 执行结果:

hello
Mr Alice
Mr Tim
Mr tu
nice to meet you

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

def decorate01(fun1):
    def wapper(*args,**kwargs):
        print('hello world')
        print('I am decorate01')
        fun1(*args,**kwargs)
    return wapper


def decorate02(fun1):
    def wapper(*args,**kwargs):
        print ('I am decorate02')
        fun1(*args,**kwargs)
        print('nice to meet you')
    return wapper


@decorate01
@decorate02
def show(*args,**kwargs):
    print (args[0])
    print (args[1])
    print (args[2])


show('Mr Alice','Mr Tim','Mr tu')


# 执行结果:

hello world
I am decorate01
I am decorate02
Mr Alice
Mr Tim
Mr tu
nice to meet you


# 观察print放置的位置不同,对应的输出结果不同。


def decorate01(fun1):
    def wapper(*args,**kwargs):
        print('hello world')
        fun1(*args,**kwargs)
        print('I am decorate01')  # 替换到了下面
    return wapper


def decorate02(fun1):
    def wapper(*args,**kwargs):
        print ('I am decorate02')
        fun1(*args,**kwargs)
        print('nice to meet you')
    return wapper


@decorate01
@decorate02
def show(*args,**kwargs):
    print (args[0])
    print (args[1])
    print (args[2])


show('Mr Alice','Mr Tim','Mr tu')


# 执行结果:

hello world
I am decorate02
Mr Alice
Mr Tim
Mr tu
nice to meet you
I am decorate01

装饰器功能扩展

#!/usr/local/python27/bin/python2.7

def 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')


# 执行结果:

before
Mr tu
after

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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/108895.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • java全局变量引起的并发问题「建议收藏」

    java全局变量引起的并发问题「建议收藏」最近刚完成了一个短彩信群发平台的开发工作,系统采用springmvc+hibernate+jdbctemplate+mysql架构。其中遇见许多问题,闲暇之余记录下来以避免在后续项目中再犯同样的错误。先看下面小段代码,一个controller,一个service。       controller.java代码:    ……..    @Autowired

    2022年8月21日
    9
  • linux 下vim删除多行「建议收藏」

    linux 下vim删除多行「建议收藏」1、按下Esc键进入命令模式2、然后输入下列命令:setnu#让当前文档内容显示行号,后面删除的时候是根据行号来删除的3、看下面例子:3,24d#敲下回车之后就会删除第3~24行的全部内容

    2022年6月15日
    135
  • Navicat 15 for MySQL激活码(在线激活)

    Navicat 15 for MySQL激活码(在线激活),https://javaforall.net/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

    2022年3月14日
    155
  • path是什么意思啊_globalmapper转换投影

    path是什么意思啊_globalmapper转换投影投影投影是JMESPath的关键特性之一。它允许您将表达式应用于元素集合。有五种投影:列表投影切片投影对象投影展平投影过滤投影处理投影需要注意的点投影分为两个步骤。左侧(LHS)创建一

    2022年7月31日
    8
  • apache的安装与配置_apache2.4安装教程

    apache的安装与配置_apache2.4安装教程准备安装包到https://www.apachelounge.com/download/下载你需要的Apache安装包(注意需要相应的VC运行库)解压文件到指定安装目录3.替换安装路径使用文本编辑器打开Apache的配置文件conf/httpd.conf执行文本替换将”c:/Apache24”全部替换成(你自己解压的路径)“G:\web\apache2.4”4

    2022年9月21日
    4
  • 如何解决高并发,秒杀问题[通俗易懂]

    如何解决高并发,秒杀问题[通俗易懂]相信不少人会被这个问题困扰,分享大家一篇这样的文章,希望能够帮到你!一、秒杀业务为什么难做?1)im系统,例如qq或者微博,每个人都读自己的数据(好友列表、群列表、个人信息);2)微博系统,每个人读你关注的人的数据,一个人读多个人的数据;3)秒杀系统,库存只有一份,所有人会在集中的时间读和写这些数据,多个人读一个数据。例如:小米手机每周二的秒杀,可能手机只有1万部,但瞬时进入的流量可能是几百几千万…

    2022年5月31日
    28

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号