• Python中装饰器的用法


    1. 定义:
      1. 装饰器本身就是一个函数
      2. 为其他函数提供附加功能
        1. 不改变源代码
        2. 不改变原调用方式
      3. 装饰器=高阶函数+嵌套函数
    2. 知识点:
      1. 函数本身就是一个变量(意味着可以被复制给一个变量:test=test(1) )
      2. 高阶函数
        1. 把函数名当成一个实参传递给另一个函数func(test1) (不改变源代码的前提下添加代码)
        2. 返回值中包含函数名return deco (不改变函数的调用方式)
      3. 嵌套函数:函数中加入新的函数def func1(): def func2():
    3. 典型结构:   
    1 def func1(test):
    2     def deco():
    3         #progress
    4     return deco#返回函数的地址,达到不改变调用方式的目的
    View Code

    完整程序:

    # __Author__Panda-J____
    
    import time
    
    
    def timer(func):  # for test1 & 2
        start_time = time.time()
        func()  # run func and test its running time
        end_time = time.time()
        print("this func running time is %s" % (end_time - start_time))
    return func
    
    @timer
    def test1():
        time.sleep(1)
        print("this is test1")
    
    
    @timer
    def test2():
        time.sleep(1)
        print("this is test2")
    
    
    test1()
    test2()
    View Code

     带参数的装饰器:

     1 # __Author__Panda-J____
     2 
     3 import time
     4 
     5 
     6 def timer(func):  # for test1 & 2
     7     def deco(*args,**kwargs):#不定参数
     8         start_time = time.time()
     9         func(*args,**kwargs)  # run func and test its running time
    10         end_time = time.time()
    11         print("this func running time is %s" % (end_time - start_time))
    12     return deco
    13 
    14 @timer
    15 def test1():
    16     time.sleep(1)
    17     print("this is test1")
    18 
    19 
    20 
    21 @timer
    22 def test2(arg1):
    23     time.sleep(1)
    24     print("this is test2,",arg1)
    25 
    26 
    27 print(test1())
    28 test2("name")

      本段程序的结果是

    this is test1
    this func running time is 1.000265121459961
    None
    this is test2, name
    this func running time is 1.0000722408294678

      问题:

      1 为什么print(test1)会为None,原因是因为在装饰器中没有返回(return)任何数值给到test1中。没有可以打印的内容。

      2 在28行中,test2有一个位置参数name传给了装饰器deco中,此处的arg=“name”

    如果装饰器本身也带参数的情况:

        需求:三层网页,分别为index,home,bbs。在登陆home和bbs页面的时候需要输入不同的用户名和密码,正确方可运行对应函数。

        思路

        1. 定义三个函数
        2. 加装饰器
        3. 用不同的用户名和密码(一个为本地Local,一个为ldap)

    完整程序

    # __Author__Panda-J____
    #语法糖

    import time
    user="jiang"
    pssw="123"
    def auth(auth_type):#多加了一层函数进行关键字嵌套
    print("auth func is",auth_type)
    def outer_wrapper(func):#相当于没有装饰器参数时候的那一层
    def wrapper(*args,**kwargs):#进行函数的装饰
    if auth_type=="local":#使用本地用户名和密码
    user_name=input("user_name:").strip()
    password=input("paassword:").strip()
    if user_name==user and password==pssw:#判定用户名和密码驶入正确
    print("33[32;1mUser authorized33[0m")
    return func(*args, **kwargs)#返回函数进行打印,如果没有这一行,不会执行home和bbs函数中的打印程序,home()将为None,因为没有返回任何内容
    else:#用户名和密码输入不正确
    exit("33[31;1mUser failed33[0m")
    elif auth_type=="ldap":#使用ldap的密码
    print("plz use ldap password")
    return wrapper
    return outer_wrapper
    def index():
    print("welcome index")
    @auth(auth_type="local")#home
    def home():
    print("welcome home")
    return "home is best"
    @auth(auth_type="ldap")
    def bbs():
    print("welcome bss")

    index()
    print(home())
    bbs()

    我所能理解的装饰器的应用场景和关键知识点都归纳了,欢迎各位指正。

             

  • 相关阅读:
    Knight Moves
    Knight Moves
    Catch him
    Catch him
    Linux查看硬件信息以及驱动设备的命令
    23种设计模式彩图
    Android开发指南-框架主题-安全和许可
    Android启动组件的三种主流及若干非主流方式
    ACE在Linux下编译安装
    void及void指针含义的深刻解析
  • 原文地址:https://www.cnblogs.com/BigJ/p/7396144.html
Copyright © 2020-2023  润新知