zoukankan      html  css  js  c++  java
  • 闭包函数、装饰器

    一、闭包函数

      闭包是指在一个函数中定义了另外一个函数,内函数运用了外函数作用域的名字,并且外函数的返回值是内函数的引用,这样就构成了一个闭包函数。

    def callFunc():
        n = 1
        def show():
            print('show: ', n)
        return show
    
    s = callFunc()
    s()
    

      去掉了全局变量的使用,将show函数封装在callFunc函数的内部,使外部不可见,不能使用show函数,隐藏了实现细节。

      程序在执行的时候,callFunc返回了内部定义的show函数,并且在show函数内部使用了外部函数的变量。

      在show函数返回时,保存了当前的执行环境,也就是会在show函数中使用外部变量n。

      n只是callFunc函数中的局部变量,当这个函数执行结束时,n自然而然就会被释放。

      但是因为callFunc函数中返回了一个show函数,show函数还在外部执行,所以程序还会将show函数所需的执行环境保存下来

    二、装饰器

      装饰器是个什么东东呢?看字面意思好像是装饰什么东东的工具,其实你猜出大概意思了,装饰器本身就是一个函数,这个函数以闭包的形式定义使用 @装饰器函数名 形式来装饰,在不改源代码的情况下,让一个程序增加功能来进行装饰。

      比如在一个项目中,有很多函数,由于项目越来越大,功能越来越多,导致程序越来越慢,其中一个功能函数功能,实现一百万次累加。

    def  my_count()
        s = 0
        for i in range(1000001):
            s += i
        print('sum:',s)
    

      现在要确定函数的运行时间,这个要怎么搞???如何能应用到所有函数上?

      解决方法:

    import time
    
    def count_time(func):
        def wrapper():      #wrapper 装饰
            start = time.time()
            func()
            end = time.time()
            print('共计执行:%s 秒'%(end - start)) # 使用%d显示,取整后是0秒,因为不到一秒
        return wrapper
    
    @count_time     # 这实际就相当于解决方法3中的 my_count = count_tiem(my_count)
    def my_count():
        s = 0
        for i in range(10000001):
            s += i
        print('sum : ', s)
    
    my_count()
    

      这样实现的好处是定义好了闭包函数后,只需要通过@xxx的装饰器语法,将@xxx加到要装饰的函数前

      多层装饰器:

    import time
     
     
    user_dic = {'is_login':None}
     
     
    def outter(func):
        def get_time(*args, **kwargs):
            start = time.time()
            res = func(*args, **kwargs)
            end = time.time()
            print('func run time:%s'%(end-start))
            return res
        return get_time
     
     
    def login_auth2(data_source,x,t):
        def login_auth(func):
            def inner(*args, **kwargs):
                if user_dic['is_login']:
                    res = func(*args, **kwargs)
                    return res
                else:
                    if data_source == 'file':
                        username = input('please input your username:')
                        password = input('please input your password:')
                        if username == 'jason' and password == '123':
                            user_dic['is_login'] = True
                            res = func(*args, **kwargs)
                            return res
                        else:
                            print('username or password error')
                    elif data_source == 'MySQL':
                        print('from MySQL')
                    elif data_source == 'ldap':
                        print('ldap')
                    else:
                        print('暂无该数据来源')
            return inner
        return login_auth
     
     
    @login_auth2('file',1,2)
    # 这一步相当于
    # res = login_auth2('file',1,2)  # 这里的res就是login_auth2()的返回值login_auth
    # @res
    @outter
    def index():
        time.sleep(1)
        print('index')
        return 'index'
     
     
    index()
    # 装饰器在装饰的时候,顺序从下往上
    # 装饰器在执行的时候,顺序从上往下
    # 这里就实现了给index函数增加了两个功能:计时和认证
    # 这里的认证函数是三层嵌套的,最外层函数的作用就是给里层函数传参
    

      装饰器模板:

      无参装饰器

    from functools import wraps
     
     
    def outter(func):
        @wraps(func)
        def inner(*args, **kwargs):  # * **在形参中使用
            # 执行被装饰函数之前你可以做的操作
            res = func(*args, **kwargs)  # * **在实参中使用
            # 执行被装饰函数之后你可以做到操作
            return res
     
        return inner
     
     
    @outter
    def index(username, *args, **kwargs):
        """index注释"""
        pass
     
     
    print(index)
    

      有参装饰器

    def wrappers(data):
        # data = 'file'
        def outter(func):
            def inner(*args,**kwargs):
                if data == 'file':
                    # 执行被装饰函数之前你可以做的操作
                    res = func(*args,**kwargs)  # * **在实参中使用
                    # 执行被装饰函数之后你可以做到操作
                    return res
            return inner
        return outter
    

      

    生前无需久睡,死后自会长眠,努力解决生活中遇到的各种问题,不畏将来,勇敢面对,加油,你是最胖的,哈哈哈
  • 相关阅读:
    .a包生成64位
    iOS教程
    iOS 难题解决日志------2层控制器 上面的控制器显示透明
    企业级的App发布流程
    如何从oc中去获取一个私有的变量.....
    iOS app的破解原理,就是去除已付费的账户信息的原理是什么?
    Could not launch "app_name"
    GCD时间轴
    Win8自动更新怎么关闭 取消Win8自动更新
    python3 elf文件解析
  • 原文地址:https://www.cnblogs.com/panshao51km-cn/p/11182781.html
Copyright © 2011-2022 走看看