• 装饰器


    1.什么是装饰器

    装饰器本质是函数, 其功能是, 装饰其他函数, 为其他函数添加附加功能

    2. 应用场景

    若我们的程序已经上线, 这时我们想为其添加新功能,原本是要修改源代码, 但是这有一定的风险,

    这时我们可以编写装饰器(新功能函数),为其需要添加新功能的部分修饰

    3 装饰器原则

     3.1 不能修改被装饰的函数的源代码

     3.2 不能修改被装饰的函数的调用方式

     3.3 装饰器被装饰的函数来说是透明的

    4. 实现装饰器的知识储备:

       4.1 函数即“变量”

       4.2 高阶函数 (什么是高阶函数)

            a. 把一个函数名 当作实参传递给另外一函数(在不修改被装饰的源代码的情况下,添加新功能)

            b. 返回值中包含 函数名 (不修改函数的调用方式)

       4.3 嵌套函数 (什么是嵌套函数)

             在一个函数体内,用def声明另外一个函数

        

    # 嵌套函数
    def foo():
        print("in the foo")
        def bar():
            print(" in the bar")
        bar() #bar 不能在外部调用, 因为它相当于一个局部变量
    foo()
    
    
    #下面是函数的调用,不是嵌套
    def test1():
        test2()
    
    test1()

    5 装饰器示例

    5.1 示例1

    import time
    def timmer(func): #test1 作为实参传入 timmer(test1)  func=test1
        def deco():
            start_time=time.time()
            time.sleep(1)
            func() #run test1()
            stop_time=time.time()
            print("the run time is %s "%(stop_time-start_time))
        return deco
    @timmer #test1=timmer(test1)
    def test1():
        print("in the test1")
    #可以用Python 语法糖@加在需要被装饰的函数钱
    #test1=timmer(test1) #timmer(test1)结果是其函数体-->return deco-->返回deco的内存地址
    print(test1) #打印test1即 deco 的内存地址
    test1()
    View Code

    先写一个高阶函数实现了“在不修改被装饰的源代码的情况下,添加新功能” ----把test1 这个函数名作为实参传入timmer这个函数

    为了不改变其调用方式,我们又利用了嵌套函数,让其返回函数名 warrper

    5.2 示例2 ---有参函数装饰器

    import time
    
    def timmer(func): # func=test2
        def deco(args): #增加text2(name)参数args
            start_time = time.time()
            time.sleep(3)
            func(args) #执行args
            stop_time = time.time()
            print("the func run time is %s"%(stop_time-start_time))
        return deco #返回deco的内存地址
    
    @timmer
    def test2(name):
        print("in the test2:",name)
    test2('frank') # test2() = deco(),要想让test2()加参数,则需要给deco加参数
    View Code

    5.3 示例3 ---装饰任意函数的装饰器

    import time
    
    def timmer(func): 
        def deco(*args,**kwargs): #如果有增加参数,如果没有不加
            start_time = time.time()
            time.sleep(3)
            func(*args,**kwargs) #执行参数,如果有的话
            stop_time = time.time()
            print("the func run time is %s"%(stop_time-start_time))
        return deco #返回deco的内存地址
    
    @timmer
    def test2(name):
        print("in the test2:",name)
    @timmer
    def test1():
        print("in the test1")
    test2('frank')# test2() = deco(),要想让test2()加参数,则需要给deco加参数
    test1()
    View Code

    5.4 示例4---终极版---装饰器也带有参数

    #!C:Program FilesPython35/bin
    # -*- conding: utf-8 -*-
    #author: Frank
    def auth(auth_type): #吸收第一层参数,装饰器的参数
        #print("auth func",auth_type)
        def out_warppage(func): #吸收第二层参数,将函数传入 func=home
            def warppage(*args,**kwargs):
                if auth_type == "local":
                    user,pwd='frank','123'
                    username = input("Username is :")
                    password = input("Password is :")
                    if username == user and password == pwd:
                        print("33[32;1myou had login succesfull33[0m")
                        res = func(*args,**kwargs) #run home(),index(),bbs()
                        return res
                    else:
                        exit("33[31;1m Invaild user/password33[0m")
                else:
                    print("Ldap 不会")
            return warppage
        return out_warppage
    
    
    def index():
        print("welcom to index page")
    @auth(auth_type="local") #当装饰器也带有参数时,我们需要在嵌套一层,
                            #装饰器的参数传给顶层函数作为实参
    def home():
        print("welcom to home page")
        return "from home"
    @auth(auth_type="ldap")
    def bbs():
        print("weblcom to bbs")
    
    index()
    bbs()
    home() #home=warapper
    View Code

    当语法糖也带有参数时, 我们需要在嵌套一层

    a. 语法糖的参数传入顶层函数,加载以何种方式装饰(“local”  or "ldap")

    b.被修饰的函数当作实参被传入第二层

    c. 在a.b 两步都准备好之后,开始执行函数,这时a.b都加载进来了,便可以自如的做判断

  • 相关阅读:
    CSS3 实现六边形Div图片展示效果
    自己编写jQuery插件 之 放大镜
    自己编写jQuery插件 之 无缝滚动
    C#装箱拆箱
    C#基础知识
    数据库锁
    SQL2008中Merge的用法
    SQl去获取相同记录
    判断DataRow中是否包含某列
    Quartz中时间表达式的设置-----corn表达式
  • 原文地址:https://www.cnblogs.com/frankb/p/6624699.html
Copyright © 2020-2023  润新知