今日总结

  • 闭包函数
  • 闭包函数的应用
  • 装饰器简介
  • 装饰器的使用
  • 装饰模板
  • 装饰器语法糖
  • 装饰器修复技术

闭包函数

# 闭包函数就是由闭函数与包函数组合而成的。闭函数就是被封闭的函数,就是函数内部的函数,只能在函数内部用;包函数指的是某个函数访问了一个来自外层函数作用域的变量。
eg:def outer():
       x = 999
   	   def inner():
            print(x)
# 'inner'就是一个闭函数,只能在'outer'函数内部用
# 所以闭包函数就是函数内部的函数引用了一个来自外层函数作用域中的变量

闭包函数的应用

# 闭包函数是给函数体传参的另外一种方式
#函数体传参的方式1:传参
eg:def index(username):
        print(username)
   index('jason') >>>>>>>>>>函数体代码需要什么就可以在形参中写什么
# 方式2:闭包
eg:def outer():
     username = 'jason'
     def index():
         print(username)  
     return index
 res = outer()

装饰器简介

# 装饰器其实就是函数里的名称空间,函数名,闭包函数组合产生的一个产物
# 装饰器的定义就是在不改变被装饰对象原有的‘调用方式’和‘内部代码’的情况下给被装饰对象添加新的功能。
#装饰器的原则就是:对扩展开放,对修改封闭

 # 时间戳就指1970年1月1号0分0秒距离刚刚代码运行间隔的秒数

装饰器的使用

eg:统一函数的执行时间
  方式1:  import time
        def index():
            time.sleep(3)>>>>>>>>>>>>>让程序原地等待三秒
            print('from index') >>>>>>>>给index函数增加了一个统计执行时间的功能
        start_time = time.time()>>>>>>>>>>>> 函数执行之前获取一个时间戳
        index()
        end_time = time.time() >>>>>>>>>>>> 函数执行之后获取一个时间戳
        print(end_time - start_time)>>>>>>>>>> 两个时间戳的差值就是函数的执行时间

 方式2:   import time
        def index():
            time.sleep(1)
            print('from index')
        def home():
            time.sleep(3)
            print('from home')
        print(home)
        def outer(func):  # 真正的index被outer局部名称空间存储了
            def get_time():
                start_time = time.time()  # 函数执行之前获取一个时间戳
                func()  # 调用了真正的index函数
                end_time = time.time()  # 函数执行之后获取一个时间戳
                print(end_time - start_time)  # 两个时间戳的差值就是函数的执行时间
            return get_time
        # res = outer(index)  # 左侧的res就是一个普通的变量名
        # res()
        # a = outer(index)  # 左侧的a就是一个普通的变量名
        # a()
        # b = outer(index)  # 左侧的b就是一个普通的变量名
        # b()
        # index = outer(index)
        # index()  # 看似调用的index其实调用的是get_time
        # print(index)  # 全局名称空间中的index指向的是get_time函数体代码
        home = outer(home)

进阶版本装饰器

# 解决的是参数问题
def outer(func_name):
    def get_time(*args, **kwargs):
        start_time = time.time()
        func_name(*args, **kwargs)
        end_time = time.time()
        print(end_time - start_time)
    return get_time

完整版本装饰器

# 解决的是返回值问题
def outer(func_name):
    def get_time(*args, **kwargs):
        start_time = time.time()
        res = func_name(*args, **kwargs)  # 执行真正的index函数
        end_time = time.time()
        print(end_time - start_time)
        # return '不要急躁' # 如何在此处返回真正index函数的返回值
        return res
    return get_time

装饰器模板

'''编写装饰器其实有一套固定的代码 不需要做任何理解'''
def outer(func_name):  # func_name用于接收被装饰的对象(函数)   
    def inner(*args, **kwargs):       
        print('执行被装饰函数之前 可以做的额外操作')       
        res = func_name(*args, **kwargs)  # 执行真正的被装饰函数        
        print('执行被装饰函数之后 可以做的额外操作')        
        return res  # 返回真正函数的返回值   
    return inner

装饰器语法糖

# 目的就是为了优化好看,内部原理:1.使用的时候最好紧跟在被装饰对象的上方。2.语法糖会自动将下面紧挨着的函数名传给@后面的函数调用
def outer(func_name):
    def inner(*args, **kwargs):
        print('执行函数之前的操作')
        res = func_name(*args, **kwargs)
        # 额外操作
        return res
    return inner

@outer  # 等价于 index = outer(index)
def index(*args, **kwargs):
    print('from index')
# index = outer(index)  # 总感觉这一行代码有点low!!!

@outer  # 等价于 home = outer(home)
def home(*args,**kwargs):
    print('from home')


print(index)
print(home)

装饰器修复技术

from functools import wraps
def outer(func_name):
    @wraps(func_name)
    def inner(*args, **kwargs):
        print('执行被装饰对象之前可以做的操作')
        res = func_name(*args, **kwargs)
        return res
    return inner
@outer
def index():
    print('from index')
@outer
def home():
    '''这是home函数的注释'''
    print('from home')
# help(home)  # help可以查看指定函数的注释信息
# help(len)
# index()  # 目前的以假乱真 有瑕疵
# print(index)
# help(home)
# help(index)
# print(home)
# print(index)
home()
index()