• python


    装饰器其实就是一个以函数作为参数,并返回一个替换函数,的可执行函数

    循序渐进的方式介绍(或直接跳到第8步看模板):

    1. 函数基础理解

    def hi(name='zhangyang'):   # 函数定义
        return 'hi ' + name
    
    
    print(hi())                 # 函数调用,打印:hi zhangyang
    
    
    # 将一个hi函数,赋值给一个greet变量(函数后跟小括号:函数调用;函数后不跟小括号:赋值)
    greet = hi
    
    print(greet)   # <function hi at 0x0000020E4C43B400>
    print(hi)      # <function hi at 0x0000020E4C43B400>
    
    print(greet())    # 打印:hi zhangyang
    print(hi())       # 打印:hi zhangyang
    
    
    # 删除hi函数
    del hi
    print(hi())      # 报错,打印:NameError: name 'hi' is not defined
    print(greet())   # 打印:hi zhangyang

    2. 在一个函数中,定义另外一个函数 

    def hi(name='zhangyang'):    # 函数定义
        print('now you are in the hi() function')
    
        def greet():   # 在函数中定义的函数
            return 'now you are in the greet() function'
    
        def welcome():
            return 'now you are in the welcome() function'
    
        print(greet())    # 调用greet()函数,并打印
        print(welcome())
        print('now you are back in the hi() function')
    
    
    hi()    # 函数调用,打印如下:
    '''
    now you are in the hi() function
    now you are in the greet() function
    now you are in the welcome() function
    now you are back in the hi() function
    '''
    greet()   # greet()函数在hi()函数体外,不能被访问,会报错。打印:NameError: name 'greet' is not defined

    3. 从函数中返回函数

    def hi(name='zhangyang'):
        def greet():
            return 'now you are in the greet() function'
    
        def welcome():
            return 'now you are in the welcome() function'
    
        if name == 'zhangyang':
            return greet   # 不带小括号,可以被传递(赋值给别的变量,而不去执行它)
        else:
            return welcome
    
    
    a = hi()         # a指向hi()函数中的greet()函数
    print(a)         # 打印:<function hi.<locals>.greet at 0x0000028001FFB840>
    
    a = hi('lisi')   # a指向hi()函数中的welcome()函数
    print(a)         # 打印:<function hi.<locals>.welcome at 0x0000028AA4D2BAE8>
    
    print(a())       # 打印:now you are in the greet() function
    print(hi()())    # 打印:now you are in the greet() function

    4. 将函数作为参数,传递给另外一个函数 

    def hi():
        return 'hi zhangyang'
    
    
    def doSomethingBeforeHi(func):   # 函数定义:将另一个函数作为形参
        print('i an doing some work before executing hi()')
        print(func())
    
    
    doSomethingBeforeHi(hi)  # 函数调用,将hi()函数传入(执行了doSomethingBeforeHi(),也执行了它中的hi()),打印如下:
    '''
    i an doing some work before executing hi()
    hi zhangyang
    '''

    5. 创建一个装饰器

    def a_new_decorator(a_func):
        def wrap_the_function():   # 定义wrap_the_function()
            print('i am doing some work before executing a_func()')
            a_func()
            print('i am doing some work after executing a_func()')
    
        return wrap_the_function   # 返回wrap_the_function()
    
    
    def a_function_requiring_decorator():    # 函数定义
        print('i am the function which needs some decoration')
    
    
    # 1. 普通函数调用
    a_function_requiring_decorator()   # ***普通函数调用,打印如下:
    '''
    i am the function which needs some decoration
    '''
    
    
    # 2. 装饰后的函数调用
    a_function_requiring_decorator = a_new_decorator(a_function_requiring_decorator)
    print(a_function_requiring_decorator)   # 打印:<function a_new_decorator.<locals>.wrap_the_function at 0x000002434CA3B7B8>
    a_function_requiring_decorator()  # ***装饰后的函数调用,调用a_new_decorator()中的wrap_the_function(),打印如下:
    '''
    i am doing some work before executing a_func()
    i am the function which needs some decoration
    i am doing some work after executing a_func()
    '''

    6. 使用@符号创建一个装饰器 

    def a_new_decorator(a_func):
        def wrap_the_function():   # 定义wrap_the_function()
            print('i am doing some work before executing a_func()')
            a_func()
            print('i am doing some work after executing a_func()')
    
        return wrap_the_function   # 返回wrap_the_function()
    
    
    @a_new_decorator    # 使用@符号,简洁的方式生成被装饰的函数
    def a_function_requiring_decoration():
        print('i am the function which needs some decoration')
    
    
    a_function_requiring_decoration()  # 函数调用,执行的是被装饰后的函数,打印如下:
    '''
    i am doing some work before executing a_func()
    i am the function which needs some decoration
    i am doing some work after executing a_func()
    '''

    ps:使用@符号和第5步中的下面一句,作用相同(使用@符号更简洁):

    a_function_requiring_decorator = a_new_decorator(a_function_requiring_decorator)

    7. wraps

    第6步中,如果直接打印被装饰函数的名称,打印不出来(函数的名字和docstring被重写了),如下:

    print(a_function_requiring_decoration.__name__)   # 打印:wrap_the_function

    需要用functools.wraps来解决这个问题,如下:

    from functools import wraps   # 导入wraps包
    
    
    def a_new_decorator(a_func):
        @wraps(a_func)   # 使用wraps处理
        def wrap_the_function():
            print('i am doing some work before executing a_func()')
            a_func()
            print('i am doing some work after executing a_func()')
    
        return wrap_the_function
    
    
    @a_new_decorator
    def a_function_requiring_decoration():
        print('i am the function which needs some decoration')
    
    
    a_function_requiring_decoration()
    '''
    i am doing some work before executing a_func()
    i am the function which needs some decoration
    i am doing some work after executing a_func()
    '''
    
    print(a_function_requiring_decoration.__name__)   # 打印:a_function_requiring_decoration

      

    8. 模板

    from functools import wraps
    
    
    def decorator_name(func):   # 装饰函数
        @wraps(func)
        def decorated(*args, **kwargs):
            if not can_run:
                return 'function will not run'
            return func(*args, **kwargs)
        return decorated
    
    
    @decorator_name
    def func():      # 函数定义
        return('function is running')
    
    
    can_run = True
    print(func())    # 函数调用,打印:function is running
    
    can_run = False
    print(func())    # 函数调用,打印:function will not run
  • 相关阅读:
    页面表单里的图片上传ENCTYPE="multipart/form-data"
    OSGI
    httpClient使用中报错org.apache.commons.httpclient.HttpMethodBase
    DNSPod--国内最早提供免费智能DNS产品的网站,致力于为各类网站提供高质量的多线智能DNS免费解析
    spring security 一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架
    Unable to parse request org.apache.commons.fileupload.FileUploadBase$IOFileUploadException: Processing of multipart/form-data request failed. null
    swfupload 上传报 security error # 2049 (security) 安全错误问题
    如何强制指定输入的参数必须为数字
    弹性盒子模型子元素垂直和水平居中
    Git常见错误处理
  • 原文地址:https://www.cnblogs.com/xiaochongc/p/12788100.html
Copyright © 2020-2023  润新知