前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python 如何理解又晕又好用的装饰器

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

作者头像
py3study
发布2020-01-09 23:16:11
4360
发布2020-01-09 23:16:11
举报
文章被收录于专栏:python3

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

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

初步理解

代码语言:javascript
复制
# 先来看一个简单函数

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.


# 现在明白了吧,只要这里明白,下面的就很好理解了。

装饰带参数的函数

代码语言:javascript
复制
# 一个参数

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

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

代码语言:javascript
复制
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

装饰器功能扩展

代码语言:javascript
复制
#!/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函数执行失败时采取什么操作。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/08/28 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档