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函数执行失败时采取什么操作。

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

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • hdu 3336 Count the string(kmp应用)

    hdu 3336 Count the string(kmp应用)ProblemDescriptionItiswellknownthatAekdyCoinisgoodatstringproblemsaswellasnumbertheoryproblems.Whengivenastrings,wecanwritedownallthenon-emptyprefixesofthisstring.

  • java在用SimpleDateFormat格式化时间时月份出现奇怪值[通俗易懂]

    这两天在做课设,关于图书管理系统的,其中在借书的记录中,时间记录的月份总是出现不正常的数值,大于12经常四十几五十几,经过对借书模块的跟踪,最后将错误定位到了时间格式化的这行代码SimpleDateFormat f = newSimpleDateFormat(“yyyy-mm-dd HH:mm:ss”);经过这行代码是要将格式化为常见的2013-07-11 09:07:20这种格式,结果经

  • 百度谷歌搜索引擎常用搜索技巧有哪些_可以用谷歌搜索的软件

    百度谷歌搜索引擎常用搜索技巧有哪些_可以用谷歌搜索的软件整理了一份史上最全搜索引擎检索技巧!

  • android studio安装教程(包安装成功,不成功你找我)

    android studio安装教程(包安装成功,不成功你找我)百度搜索Androidstudio,或者直接输入http://www.android-studio.org进入这个页面根据这个下载相应的安装包或者压缩包。这里演示安装64位的androidstudio下载完成后直接双击安装包,就会出来下面这个界面点击Next点击Next点击Next点击i…

  • Nginx搭建视频点播和视频直播服务器[通俗易懂]

    Nginx搭建视频点播和视频直播服务器[通俗易懂]Nginx搭建视频点播和视频直播服务器一·、环境:Centos7,(推荐,Ubuntu不是很好用,经常会有一些莫名其妙的报错)Nginx1.10.1二、系统环境搭建首先,我是不建议自己一个个去安装这些软件的,耗时耗力,而且,容易出错,所以,最好使用yuminstall***命令安装,出错的概率小。资源链接:链接:https://pan.baidu.com/s/1WmJYpQ_b…

  • 关闭防火墙 linux_linux系统防火墙关闭

    关闭防火墙 linux_linux系统防火墙关闭抛开实际生产环境个人平时练习的时候安装虚拟机可能遇到过很多坑就很烦,可能很大一部分原因都是防火墙没关掉哈哈哈哈所以建议永久性关闭防火墙下面是CentOs7关闭防火墙的命令!1:查看防火状态systemctlstatusfirewalld如果是这样就开着呢如果是这样就是关着2:暂时关闭防火墙systemctlstopfirewalld3:重启防火墙systemctlenablefirewalld5:永久关闭后重启Linux永久关闭防火墙firewalld和selli

发表回复

您的电子邮箱地址不会被公开。

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