zoukankan      html  css  js  c++  java
  • Python函数-6 装饰器

    装饰器
    装饰器(Decorator):从字面上理解,就是装饰对象的器件。可以在不修改原有代码的情况下,为被装饰的对象增加新的功能或者附加限制条件或者帮助输出。装饰器有很多种,有函数的装饰器,也有类的装饰器。装饰器在很多语言中的名字也不尽相同,它体现的是设计模式中的装饰模式,强调的是开放封闭原则。装饰器的语法是将@装饰器名,放在被装饰对象上面。

    @dec
    def func():
        pass
    

    在介绍装饰器之前,先要了解几个知识点

    重名函数会怎么样?

    def test():
    	print('1')
    def test():
    	print('2')
    test()
    这个时候会输出什么?
    会输出2,后面的会覆盖前面的函数
    -----------------------------------
    def foo():
    	print('test')
    foo = lambda x:x+1
    foo()
    此时foo()的执行结果是什么?
    foo会执行匿名函数的内容,而不会执行函数foo,打印test
    

    接下来就是一个比较经典的案例了,有一个大公司,下属的基础平台部负责内部应用程序及API的开发。另外还有上百个业务部门负责不同的业务,这些业务部门各自调用基础平台部提供的不同函数,也就是API处理自己的业务,情况如下:
    基础平台部门提供的功能如下:

    def f1():
    	print("业务部门1的数据接口......")
    def f2():
    	print("业务部门2的数据接口......")
    def f3():
    	print("业务部门3的数据接口......")
    def f100():
    	print("业务部门100的数据接口......")
    各部门分别调用基础平台提供的功能
    f1()
    f2()
    f3()
    f100()
    

    目前公司发展壮大,但是以前没有考虑到验证相关的问题,即:基础平台提供的功能可以被任何人使用。现在需要对基础平台的所有功能进行重构,为平台提供的功能添加验证机制,执行功能前,先进行验证 老大把工作交给A,他是这么做的: 跟每个业务部门交涉,每个业务部门自己写代码,调用基础平台的功能之前先验证。这样一来基础平台就不需要做任何修改了。 当前A被老大开除了 老大又把工作交给B,他是这么做的:

    def f1():
        # 验证1
        # 验证2
        # 验证3
    def f2():
        # 验证1
        # 验证2
        # 验证3
    过了一周B也被开除了。。。。。。。。。。
    

    老大又把工作交给C,他是这么做的:

    def check_login()
        # 验证1
        # 验证2
        # 验证3
    def f1():
    	check_login()
    def f2():
    	check_login()	
    

    老大说写代码要遵循开放封闭的原则,虽然在这个原则是用的面向对象开发,但是也适用于函数式编程,简单来说,已经实现的功能不允许修改,但可以被扩展 。

    封闭:已实现的功能代码块

    开放:对扩展开发

    老大给出了方案,
    def foo():
    	def inner():
        	验证1
        	验证2
        	验证3
    	    result = func()
    	    return result
    return inner
    
    @foo
    def f1():
    	pass
    @foo
    def f2():
    	pass
    

    看不懂?没关系,接下来写一个简单点的

    def w1(func):
    	def inner():
    		print('正在验证权限')
    		func()
    	return inner
    	
    def f1():
    	print('f1')
    
    innerFunc = w1(f1)        # innerFunc = inner
    innerFunc()               # inner()
    
    f1 = w1(f1)
    f1()
    
    def outer(func):
        def inner():
            print("认证成功!")
            result = func()
            print("日志添加成功")
        return inner
    
    @outer              # f1 = outer(f1) = inner
    def f1():
        print("业务部门1数据接口......")
    
    f1()    
    
    1 程序开始运行,从上往下解释,读到def outer(func):的时候,发现这是个“一等公民”函数,于是把函数体加载到内存里,然后过。
    2 读到@outer的时候,程序被@这个语法糖吸引住了,知道这是个装饰器,按规矩要立即执行的,于是程序开始运行@后面那个名字outer所定义的函数。
    3 程序返回到outer函数,开始执行装饰器的语法规则。
    规则是:被装饰的函数的名字会被当作参数传递给装饰函数。装饰函数执行它自己内部的代码后,会将它的返回值赋值给被装饰的函数。原来的f1函数被当做参数传递给了func,而f1这个函数名之后会指向inner函数
    

    两个装饰器

    def makeBold(fn):
        def wrapped():
            return "<b1>" + fn() + "</b1>"
        return wrapped
    
    def makeItalic(fn):
        def wrapped():
            return "<b2>" + fn() + "</b2>"
        return wrapped
    
    
    
    @makeBold       # test3 = makeBold(test3)   =  wrapped
    @makeItalic     # test3 = makeItalic(test3) =  wrapped
    def test3():
        return "hello world"
    
    print(test3())
    

    装饰器的执行时间

    def w1(func):
        print("--正在装饰--")
        def inner():
            print("--正在权限验证--")
            func()
        return inner
    
    # 只要Python解释器执行到了这个代码,那么就会自动的进行装饰,而不是等到调用的时候才进行装饰
    @w1     # f1 = w1(f1)
    def f1():
        print("--f1--")
    
    # 在调用f1前已经装饰了
    f1()
    

    练习

    def w1(func):
        print("正在装饰1")
        def inner():
            print("正在验证权限1")
            func()
        return inner()
    
    def w2(func):
        print("正在装饰2")
        def inner():
            print("正在验证权限2")
            func()
        return inner()
        
    @w1
    @w2
    def f1():
        print("--f1--")
    f1()
    
  • 相关阅读:
    ibatis的log4配置
    ie6中DIV最小高度
    Redhat GRUB配置错误修复
    MySQL性能优化的21条经验
    Top 200的全球开发者BLOG
    IBM服务器配置内外网络配置
    php ftp_rawlist不显示目录问题
    PHP实现异步调用方法研究[转]
    20100823工作记录
    Web 2.0应用客户端性能问题十大根源
  • 原文地址:https://www.cnblogs.com/sakura579/p/12422159.html
Copyright © 2011-2022 走看看