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面试不会怎么办_【必须录用】面试遇到不会回答的问题,该怎么办?一.前言今天给大家讲讲面试过程当中最长遇到的窘境,也是最能体现一个候选人临场应变能力的地方,那就是当我们在面试的过程当中,遇到的问题回答不上来的时候,该怎么办。二.误区在开始讲解之前,先纠正一个误区,那就是对于一场面试而言,最后的结果好坏并不完全取决于面试当中的问题是否都回答了上来。能不能录取和是否回答出所有问题并没有直接的联系。换句话说,我自己经历过的,无论是面试也好,还是面别人也罢,问题没…

    2022年7月9日
    24
  • HTML 有序列表 字母,HTML之有序列表教程

    HTML 有序列表 字母,HTML之有序列表教程HTML之有序列表教程信息有时候是无序归纳的,有的却有着明确的顺序,在上一篇也提到了。那么简单的来想一下身边有哪些事物是有先后顺序的:操作步骤、排行榜、书目录……以前我们面对这些有着顺序或是有数字注明排序的内容时大多是在数据前自行加上一个数值,或是由程序加上这个数值。而如果使用有序列表则不需要这么麻烦,根本不用自行去填写序数,当单层列表的时候这种特性似乎并不明显,而当使用多层的时候其特性就很明显了…

    2022年6月26日
    33
  • JAVA四舍五入保留一位小数

    JAVA四舍五入保留一位小数newBigDecimal(speed).setScale(1,BigDecimal.ROUND_HALF_UP).doubleValue()

    2022年5月11日
    57
  • java websocket client_前端和后端哪个累

    java websocket client_前端和后端哪个累一.WebSocket简单介绍随着互联网的发展,传统的HTTP协议已经很难满足Web应用日益复杂的需求了。近年来,随着HTML5的诞生,WebSocket协议被提出,它实现了浏览器与服务器的全双工通

    2022年8月4日
    7
  • emWin 2天速成实例教程000_如何快速入门ucGUI/emWin

    emWin 2天速成实例教程000_如何快速入门ucGUI/emWinemWin是一个嵌入式GUI图形库,GUI图形库的概念就好像它是一个平台,我们只需要在这个平台上通过其提供的方法写自己的用户界面应用程序就行,非常简单、便捷。如果没有这个GUI图形库,我们的应用程序还需要考虑按键、编辑框、下拉菜单等控件的绘制和实现,还需要管理各个控件、窗口、页面它们之间的相互关系,还需要做触摸屏/鼠标/键盘的管理等等,这是非常麻烦而且容易出错的事情…

    2022年10月14日
    3
  • zookeeper启动报错 ,无法加载主类_security与safe

    zookeeper启动报错 ,无法加载主类_security与safe最近在本机电脑上zookeeper集群,但是报错如下,哪位大佬知道怎么解决2020-07-1314:43:15,283[myid:]-INFO[main:QuorumPeerConfig@173]-Readingconfigurationfrom:/home/yangaoyu/software/zookeeper-3.6.1/bin/…/conf/zoo.cfg2020-07-1314:43:15,316[myid:]-INFO[main:QuorumPeerConfi

    2022年8月30日
    4

发表回复

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

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