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

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

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

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 归档
http://www.vxiaotou.com