zoukankan      html  css  js  c++  java
  • python函数(三)—装饰器

    一、闭包函数

    定义在内部的函数,包含对外部作用域而非全局作用域的引用,该函数就成为闭包函数

    import time
    def timmer():
          def wrapper():
        print('=======执行结果') 
      return wrapper

    print(timmer())

    timmer()()

    二、装饰器修饰别人的工具,修饰添加功能,工具指的是函数

    装饰器本身可以是任何可调用对象

    原因:

    为什么要使用装饰器

    开放封闭原则:对修改是封闭的,对扩展是开放的

    装饰器就是为了在不修改被装饰对象的源代码以及调用方式的前提下,为期添加新功能

    (一)无参装饰器

    1.无返回值

    import time
    def timmer(func):
        def wrapper():
            start_time=time.time()
            func()
            stop_time=time.time()
            print('运行时间是:%s'%(stop_time-start_time))
        return wrapper
    
    @timmer
    def compute_time():
        time.sleep(3)
        print('=========运行结束')
        
    compute_time()
    View Code

    修饰器修饰其正下方的函数--compute_time,他将compute_time作为参数传递给自己,返回带compute_time参数的闭包函数--wrapper,而执行闭包函数的过程中又会去调用修饰器修饰的函数compute_time(因为本身被作为参数传递了进来,加括号即运行)执行而返回结果

    2.捕获返回值

    如果被修饰的函数带有返回值,那么如何获取返回值呢?

    这就需要在闭包函数中接收这个返回值,并将其return出来

    import time
    def timmer(func):
        def wrapper():
            start_time=time.time()
            res=func()
            stop_time=time.time()
            print('运行时间是:%s'%(stop_time-start_time))
            return res
        return wrapper
    
    @timmer
    def compute_time():
        time.sleep(3)
        print('=========运行结束')
        return 1
    
    # compute_time()
    print(compute_time())
    View Code

    3.参数传递

    import time
    def timmer(func):
        def wrapper(*args,**kwargs):
            start_time=time.time()
            res=func(*args,**kwargs)
            stop_time=time.time()
            print('运行时间是:%s'%(stop_time-start_time))
            return res
        return wrapper
    
    @timmer
    def compute_time(name):
        time.sleep(3)
        print('欢迎%s回来'%name)
        print('=========运行结束')
        return 1
    
    @timmer
    def foo():
        time.sleep(1)
        print('普通调用')
        return 2
    
    print(compute_time('larry'))
    print(foo())
    View Code

    (二)有参装饰器

    import time
    def timmer(func):
        def wrapper(*args,**kwargs):
            print('====>timmer.wrapper')
            start_time=time.time()
            res=func(*args,**kwargs) #auth_wrapper
            stop_time=time.time()
            print('run time is %s' %(stop_time-start_time))
            return res
        return wrapper
    
    
    
    login_user={'user':None,'status':False}
    def auth(driver='file'):
        def auth2(func):
            def wrapper(*args,**kwargs):
                print('=======>auth.wrapper')
                time.sleep(5)
                if driver == 'file':
                    if login_user['user'] and login_user['status']:
                        res=func(*args,**kwargs)
                        return res
                    else:
                        name=input('>>: ')
                        password=input('>>: ')
                        if name == 'egon' and password == '123':
                            login_user['user']='egon'
                            login_user['status']=True
                            print('33[45mlogin successful33[0m')
                            res=func(*args,**kwargs)
                            return res
                        else:
                            print('33[45mlogin err33[0m')
                elif driver == 'ldap':
                    print('==========ldap的认证')
                elif driver == 'mysql':
                    print('==========mysql的认证')
                    return func(*args,**kwargs)
                else:
                    print('=========未知的认证来源')
            return wrapper
        return auth2
    
    
    @auth('file') #@auth2====>index=auth2(index)===>index=auth_wrapper
    @timmer #index=timmer(auth_wrapper) #index=timmer_wrapper
    def index():
        time.sleep(3)
        print('welcome to index page')
    @auth(driver='mysql')
    def home(name):
        print('%s welcome to home page' %name)
    index() 
    View Code

    对于内部函数来说,外部传入的参数总是可见的,所以如果需要为装饰器传递参数的话,可以在装饰器的外层包裹一层传递参数的函数将需要传递的参数传递进

  • 相关阅读:
    2016年10月30日表单标签与样式表分类和选择器
    2016年10月29日常用标签与表格
    2016年10月28日网页属性和通用标签
    10月27日体会目标
    字符串学习笔记
    [51nod1789] 跑得比谁都快
    [洛谷9月月赛]签到题
    [LUOGU2730] 魔板
    [SCOI2009]迷路
    [51nod1074] 约瑟夫问题 V2
  • 原文地址:https://www.cnblogs.com/geek-ace/p/6913700.html
Copyright © 2011-2022 走看看