zoukankan      html  css  js  c++  java
  • day4-装饰器

    一 概述

    装饰器:本质是函数

    功能:用来装饰其他函数,为其他函数添加附加功能

    二 装饰器原则

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

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

    三 实现装饰器的知识储备

    函数即“变量”

    高阶函数

    嵌套函数

    最终:高阶函数+嵌套函数 =》 装饰器

    1. 高阶函数

    实现高阶函数的两个条件:

    把一个函数名当作实参传给另一个函数

    返回值中包含函数名

    条件1作用:在不修改被装饰函数源代码的情况下为其添加功能

    import time
    
    def bar():
        time.sleep(1)
        print("in the bar")
    
    def test(func):
        print(func)
        start_time = time.time()
        func()
        stop_time = time.time()
        print("the func run the is %s " % (stop_time-start_time))
    
    #没有修改bar的源代码
    test(bar)  #把bar函数名当作实参传到test中
    
    #输出
    <function bar at 0x033AD6A8>
    in the bar
    the func run the is 1.0007984638214111
    

    没有修改bar函数的源代码,但是调用方式改变了

    条件2作用:不修改函数的调用方式

    import time
    
    def bar():
        time.sleep(1)
        print("in the bar")
    
    def test(func):
        print(func)
        start_time = time.time()
       func() stop_time = time.time() print("the func run the is %s " % (stop_time-start_time)) return func #返回函数内存地址 bar = test(bar) bar() #没有改变bar函数调用方式 #输出 <function bar at 0x027FD6A8>
    in the bar the func run the is 0.0 in the bar

    没有修改bar函数的调用方式和源代码,但是输出结果改变了

    2. 嵌套函数

    定义:在一个函数的函数体内用def 去声明一个函数,而不是去调用其他函数,称为嵌套函数

    def foo():
        print("in the foo")
        def bar():
            print("in the bar")
        bar()
    
    foo()
    
    #输出
    in the foo
    in the bar
    

    四 装饰器定义

    1. 定义

    装饰器实现的条件:高阶函数+嵌套函数 =》装饰器

    import time
    #定义装饰器
    def timmer(func):
        def deco():
            stat_time = time.time()
            func()
            stop_time = time.time()
            print("the func run time is %s" % (stop_time-stat_time))
    
        return deco
    
    #装饰test函数
    @timmer  #@timmer相当于test = timmer(test)
    def test():
        time.sleep(1)
        print("in the test")
    
    test()
    
    #输出
    in the test
    the func run time is 1.0006682872772217
    

     执行步骤:

    1.执行timmer函数,timmer(test)返回值赋值给test变量,即test = timmer(test)

    2.此时的test的值是执行timmer函数返回值deco,即test = deco

    3. 所以执行test,其实就是执行的是deco函数,test()就是执行deco函数

    2. 执行函数带参数

    import time
    #定义装饰器
    def timmer(func):
        def deco(*args,**kwargs):  #传入非固定参数
            stat_time = time.time()
            func(*args,**kwargs)  #传入非固定参数
            stop_time = time.time()
            print("the func run time is %s" % (stop_time-stat_time))
    
        return deco
    
    #装饰test函数
    @timmer  #@timmer相当于test = timmer(test)
    def test(name,age):  #带参数
        time.sleep(1)
        print("name: %s, age:%d" % (name,age))
    
    @timmer
    def test1():  #不带参数
        time.sleep(1)
        print("in the test1")
    
    test("alex",22)
    test1()
    
    #输出
    name: alex, age:22
    the func run time is 1.0008456707000732
    in the test1
    the func run time is 1.0008673667907715
    

     3.执行函数有返回值

    def timmer(func):  #func = test
        def deco(*args,**kwargs):
            res = func(*args,**kwargs)  #函数执行结果返回值赋给res
            return res  #返回res
        return deco
    
    @timmer
    def test():
        print("in the test")
        return "from the test"  #执行函数rest有返回值
    
    res = test()
    print(res)
    
    #输出
    in the test
    from the test
    

    4. 装饰器带参数

    之前我们的装饰器都是没有带参数的,其实我们已经能解决90%的问题了,但是如果说有一种情况:就是在你访问不同页面时,你用的验证的方式来源不同,这时就要用到带参数的装饰器了。

    user,passwd = "alex","abc123"
    
    def auth(auth_type): #传递装饰器的参数
        print("auth func:",auth_type)
        def out_wrapper(func):  #将被装饰的函数当作实参传递进来
            def wrapper(*args,**kwargs):  #将被装饰的函数的参数传递进来
                #print("wrapper func args:",*args,**kwargs)
                username = input("username:").strip()
                password = input("password:").strip()
                if auth_type == "local":
                    if user == username and passwd == password:
                        print("33[31;1mUser has passed authentication33[0m")
                        res = func(*args,**kwargs)
                        return res
                    else:
                        exit("Invalid username or password")
                elif auth_type == "ldap":
                    pass
            return wrapper
        return out_wrapper
    
    def index():
        print("welcome to index page")
    
    @auth(auth_type="local") #带参数装饰器
    def home():
        print("welcome to home page")
        return "from home"
    
    @auth(auth_type="ldap")  #带参数装饰器
    def bbs():
        print("welcome to bbs page")
    
    index()
    print(home())
    bbs()
    

     从上面的例子可以看出,执行步骤:

    1. out_wrapper = auth(auth_type="local")

    2. home = out_wrapper(home)

    3. home()

    所以这个函数的作用分别是:

    1. auth(auth_type) 传递装饰器参数

    2. out_wrapper(func) 把函数当作实参传递进来

    3. wrapper(*args,**kwargs) 真正执行装饰的函数

  • 相关阅读:
    CentOS7 Failed to start LSB: Bring up/down解决方法
    【转】Java包管理器Maven学习
    Android开发-API指南-<category>
    Android开发-API指南-<application>
    Android开发-API指南-<activity-alias>
    Android开发-API指南-<activity>
    Android开发-API指南-<action>
    Android开发-API指南-Android简介
    Android开发-API指南-Activity
    Android开发-API指南-应用程序开发基础
  • 原文地址:https://www.cnblogs.com/Easonlou/p/8334778.html
Copyright © 2011-2022 走看看