码迷,mamicode.com
首页 > 编程语言 > 详细

python当中的装饰器

时间:2018-12-14 21:07:46      阅读:175      评论:0      收藏:0      [点我收藏+]

标签:flag   步骤   family   装饰器   people   rgs   font   函数   完整   

1.装饰器

  首先我们来说一下一个软件的设计原则:开闭原则,又被称为开发封闭原则,你的代码对功能的扩展是开放的,你的程序对修改源代码是封闭的.这样的软件设计思路可以更好的维护和开发.

  开放:对功能扩展开放

  封闭:对修改代码封闭

  接下来我们看装饰器.首先我们先模拟一下女娲造人.

def  create():
    print(‘女娲很厉害,捏个泥人吹口气就成了人‘)

create_people()

  现在我们让这个函数加个浇水功能.

def  create():
    print(‘浇水‘)
    print(‘女娲很厉害,捏个泥人吹口气就成了人‘)

create_people()

  但是,现在就违反了开闭原则,如果每次要添加新功能,那这样就等于是修改了源代码.因为开闭原则对修改是封闭的,那怎么办,我们可以这样做

def water():
    print(‘先浇水‘)
    create()
water()

  这样做的问题是.函数写好了,重新创建了这个函数,在这之前访问过这个函数的人必须要修改代码来访问新的函数water(),所以现在就用到了装饰器,装饰器的作用就是在不修改原有代码的基础上,给函数扩展功能

def create_people():
    print(‘女娲很厉害随随便便就造人‘)
def water(fn):
    def inner():
        print(‘浇浇水‘)
        fn()
        print(‘施肥‘)
    return inner

# # create_people() # 这个就不行了.
# warter() # 访问浇水就好了

# func = water(create_people)
# func() # 有人问了. 下游访问的不不依然是func么, 不不还是要改么?
create_people = water(create_people)
create_people() # 这回就好了吧

 说一下执行流程:

技术分享图片

结论: 我们使用water函数把create_people给包装了一下. 在不修改create_people的前提下.
完成了对create_people函数的功能添加

 

下面我们给出装饰器的完整模型代码

def wrapper(fn):  # fn是目标函数
    def inner(*args,**kwargs):  # 为了目标函数的传参
        ‘‘‘这里是执行函数前的内容‘‘‘
            ret = fn(*args,**kwargs)  # 调用目标函数,ret是目标函数的返回值
        ‘‘‘这里是执行目标函数后的内容
            return ret  # 把目标函数的返回值返回.保证函数正常的结束
    return inner

@wrapper  # 这里是语法糖
def func():
    print(‘我是目标函数")

func() # 调用目标函数

  

二.带参数的装饰器

  注意: 咱们之前的写法是@wrapper 其中wrapper是一个函数. 那么也就是说. 如果我能让wrapper这里换成个函数就行了了. wrapper(True)返回的结果是wrapper也是?一个函数啊. 刚刚

好和前面的@组合成一个@wrapper. 依然还是原来那个装饰器. 只不过这里套了3层. 但你要
能看懂. 其实还是原来那个装饰器@wrapper

  

  执行步骤:    

    先执行wrapper(True) 然后再@返回值. 返回值恰好是wrapper. 结果就是@wrapper

下面是装饰器传参的通用写法

def wrapper_out(flag):
    def wrapper(fn):
        def inner(*args,**kwargs):
            if flag == True:
                ‘‘‘执行目标函数前的位置‘‘‘
                ret = fn(*args,**kwargs)
                ‘‘‘执行目标函数后的位置‘‘‘
                return ret
            else:
                ret = fn(*args,**args)
                return ret
        return inner
    return wrapper

@wrapper_out
def func():
    print(‘这里是目标函数‘)
    
func()
                

  

三.多个装饰器装饰同一个函数

def wrapper1(fn):
    def inner(*args,**kwargs):
        print(‘111‘)
        ret = fn(*args,**kwargs)
        print(‘222‘)
    return inner

def wrapper2(fn):
    def inner(*args,**kwargs):
        print(‘333‘)
        ret = fn(*args,**kwargs)
        print(‘444‘)
    return inner

def wrapper3(fn):
    def inner(*args,**kwargs):
        print(‘555‘)
        ret = fn(*args,**kwargs)
        print(‘666‘)
    return inner

@wrapper1
@wrapper2
@wrapper3
def eat():
    print(‘我想吃水果‘)

eat()

  技术分享图片

 

执?顺序: 首先@wrapper1装饰起来. 然后获取到?个新函数是wrapper1中的inner. 然后执
行@wrapper2.这个时候. wrapper2装饰的就是wrapper1中的inner了了. 所以. 执行顺序就像:
第?层装饰器前(第?层装饰器前(目标)第一层装饰器后)第二层装饰器后. 程序从左到右执行
起来. 就是我们看到的结果

 

 

 

 

 

 

 

 

 

 

  

python当中的装饰器

标签:flag   步骤   family   装饰器   people   rgs   font   函数   完整   

原文地址:https://www.cnblogs.com/robertx/p/10121428.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!