Day13课后有感

今日内容概要

  • 闭包函数(重要)

  • 闭包函数的实际应用

  • 装饰器简介(重点+难点)

  • 简易版本装饰器

  • 进阶版本装饰器

  • 完整版本装饰器

  • 装饰器模板(拷贝使用即可)

  • 装饰器语法糖

  • 装饰器修复技术

 

 

闭包函数(重要)

 

# 闭包函数的两大特征
	1.闭:定义在函数内部的函数  # 函数内的嵌套函数,只能在函数内部用

  2.包:内部函数使用了外层函数名称空间中的名字  # 函数内的嵌套函数访问了外层函数的变量
 
def outer():
    x = 999
    def inner():  # 嵌套函数
        print('from outer>>>inner',x)
    return inner  #有返回值 
x = 666
res = outer()  # 访问外层函数
res()

  

闭包函数的实际应用

  闭包函数是给函数体传参的另外一种方式


函数体传参的方式1: 形参

def index(username):
    print(username)
index('jason')  # jason就是给index变量名传参,参数都是自定义的,传什么看你心情~

 

函数体传参的方式2:闭包 

def outer(username):
    def index():
        print(username)  
    return index
res = outer('kevin')  # 形参username与值kevin临时绑定 >>>:outer局部名称空间中
res()
res1 = outer('jason')  # 形参username与值kevin临时绑定 >>>:outer局部名称空间中
res1()

  

装饰器简介

定义:

  在不改变被装饰函数原有的'调用方式'和'内部代码'的情况下给被函数添加新的功能,只能提添加功能,不能修改原有代码。

 

什么是时间戳?

import time
print(time.time())  # 1647568920.168808
'''上述的注释数字是时间戳:1970年1月1日0时0分0秒距离刚刚代码运行间隔的秒数'''
time.sleep(3)  # 让程序原地等待三秒
print('hello world')

 

运用时间戳统计程序执行的时间

import time
def index():
    time.sleep(3)  # 让程序原地等待三秒
    print('666')

'''给index函数增加了一个统计执行时间的功能'''
start_time = time.time()  # 函数执行之前获取一个时间戳
index()
end_time = time.time()  # 函数执行之后获取一个时间戳
print(end_time - start_time)  # 两个时间戳的差值就是函数的执行时间

  

简易版本装饰器

import time
def index():
    time.sleep(1)
    print('666')
def home(a):
    time.sleep(3)
    print('666')
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):
    def get_time(*args, **kwargs):  # 括号内运用到可变长参数
        start_time = time.time()
        func(*args, **kwargs)
        end_time = time.time()
        print(end_time - start_time)
    return get_time

  

完整版本装饰器

# 解决的是返回值问题
def outer(func):
    def get_time(*args, **kwargs):
        start_time = time.time()
        res = func(*args, **kwargs)  # 执行真正的index函数
        end_time = time.time()
        print(end_time - start_time)
        return res
    return get_time

  

 

如果你实在搞不懂装饰器的逻辑,装饰器模板拿去用(重要)

'''编写装饰器其实有一套固定的代码 这套你拿着走哪用哪,随用随调'''
def outer(func):  # func用于接收被装饰的对象(函数)
    def inner(*args, **kwargs):
        print('执行被装饰函数之前 可以做的额外操作')
        res = func(*args, **kwargs)  # 执行真正的被装饰函数
        print('执行被装饰函数之后 可以做的额外操作')
        return res  # 返回真正函数的返回值
    return inner

  

装饰器语法糖  @可甜了可省事了

语法糖内部原理:
  1.使用的时候最好紧跟在被装饰对象的上方


  2.语法糖会自动将下面紧挨着的函数名传给@后面的函数调用

# 仅仅是让代码编写的更加好看、简洁!!!  
def outer(func): def inner(*args, **kwargs): print('执行函数之前的操作') res = func(*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)

  

装饰器修复技术(说好的修复实际是做1:1高仿)

黄色标注部分是固本模版直接cv即可,从此你和真的就看不出区别了~

from functools import wraps   # 照抄即可
def outer(func):
    @wraps(func_)  # 照抄即可
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可以查看指定函数的注释信息

  

 

 

posted @ 2022-03-20 17:27  ji哩咕噜  阅读(24)  评论(0编辑  收藏  举报