今日内容

  • 闭包函数

  • 闭包函数的实际应用

  • 装饰器简介

  • 简易版本装饰器

  • 进阶版本装饰器

  • 完整版本装饰器

  • 装饰器模板

  • 装饰器修复术

 

闭包函数

#闭包函数的两大特征:
1.闭:定义在函数内部的函数
2.包:内部函数使用了外层函数名称空间中的名字
def outer():
  x = 777
  def inner():
      print('qqqq',x)
  return inner
x = 666
res = outer()
res()

 

闭包函数的实际应用

#闭包函数是给函数体传参的另一种方式
#函数体传参的方式1:形参
def index(id):
print()
#函数体代码需要什么就在形参中写什么
index('kk')

#函数体传参的方式2:闭包
def outer():
# id = 'kk'
def index():
print(id) # 永远使用的都是kk
return index
res = outer('tt') # 形参id与值tt临时绑定
>>>:outer局部名称空间中
res1 = outer('kk') # 形参id与值kk临时绑定
>>>:outer局部名称空间中
res1()

 

装饰器简介

装饰器的本质:
在不改变被装饰对象原有的调用方式和内部代码的情况下给装饰对象添加新的功能

装饰器的原则:
对扩展开放 对修改封闭

简易版本装饰器

import time
def index():
  time.sleep(1)
  print('from')
'''给index函数增加一个统计执行时间的功能'''
start_time = time.time() # 函数执行之前获取一个时间戳
index()
end_time = time.time() # 函数执行之后获取一个时间戳
print(end_time - start_time)

通过传参的方式
缺陷1:
代码写死了 无法统计其他函数的执行时间
能否解决?
可以 将函数名通过形参的形式传入
缺陷2:
封装成函数之后 调用方式改变了 不符合装饰器原则
能否解决?
不可以
# s = 'yplwertlyuu'
# l = ''
# for i in s:
#     if i in l:
#         break
#     else:
#         l += i
# print(len(l))


# def func():
#     print('from func')
#     return index # 将函数名当做返回值
# def index():
#     print('from index')
# res = func() # res接收函数名
# print(res) # 指向的是index函数的内存地址
# res() # index()



# def outer(func_name):
#     def inner(*args,**kwargs):
#         res = func_name(*args,**kwargs)
#         username = input('username:').strip()
#         pwd = input('pwd:').strip()
#         if username == 'jason'and pwd == '123':
#             print('认证成功')
#         else:
#             print('认证失败')
#         return res
#     return inner()
# @outer
# def index(*args,**kwargs):
#     pass

# a = {
#     'is_userlogin':False,
#     'username':'jason',
#     'pwd':'123'
# }
#
#
# def login(func):
#     def inner(*args,**kwargs):
#         if a['is_userlogin'] == False:
#             usename = input('usename:')
#             pwd = input('pwd:')
#             if usename == a['username'] and pwd == a['pwd']:
#                 print('登陆成功')
#                 a['is_userlogin '] = True
#                 func(*args,**kwargs)
#             else:
#                 print('用户名或密码错误')
#
#         else:
#             print('用户已登录')
#             func(*args,**kwargs)
#     return inner
#
# @login
# def index(*args,**kwargs):
#     pass
# index()




# a = {'userlogin':False}
#
# def login(func):
#     def inner(*args,**kwargs):
#         if a['userlogin'] == False:
#             username = input('username:')
#             pwd = input('pwd:')
#             if username == 'jason' and pwd == '123':
#                 print('登陆成功')
#                 a['userlogin'] = True
#                 func(*args,**kwargs)
#             else:
#                 print('用户名或密码错误')
#
#         else:
#             print('用户已登录')
#             func(*args,**kwargs)
#     return inner
#
# @login
# def index(*args,**kwargs):
#     pass
# index()



# def outer():
#     x = 777
#     def inner():
#         print('qqqq',x)
#     return inner
# x = 666
# res = outer()
# res()

#
# import time
# def index():
#     time.sleep(1)
#     print('from')
# '''给index函数增加一个统计执行时间的功能'''
# start_time = time.time() # 函数执行之前获取一个时间戳
# index()
# end_time = time.time() # 函数执行之后获取一个时间戳
# print(end_time - start_time)



import time
def index():
  time.sleep(1)
  print('from index')
def home():
  time.sleep(2)
  print('from home')
print(home)
def outer(func): # 真正的index被outer局部名称空间存储了
  def get_time():
      start_time = time.time()
      func() #调用了真正的函数
      end_time = time.time()
      print(end_time - start_time)
  return get_time
index = outer(index)
index() # 看似调用的是index其实调用的是get_time
print(index) #全局名称空间中index指向的是get_time函数体代码
home = outer(home) #左侧的home就是普通的变量名

进阶版装饰器

# 解决的是参数问题
import time
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()

完整版装饰器

#解决的是返回值问题
import 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 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

装饰器语法糖

#仅仅是让代码编写得更好看、简洁
def outer(func_name):
  def inner(*args, **kwargs):
      print('执行函数之前的操作')
      res = func_name(*args, **kwargs)
      # 额外操作
      return res
  return inner
@outer # 等价于 home = outer(home)
def home(*args,**kwargs)
print('from home')

print(index)
print(home)

语法糖内部原理
1.使用的时候最好紧跟在被装饰对象的上方
2.语法糖会自动将下面紧挨这的函数名@后面的函数调用

装饰器修复技术

#本质不变,却做到比真的还真

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 home():
  pass
help(home) # help可以查看指定函数的注释信息



 posted on 2022-03-18 23:33  鳗鱼的春天  阅读(164)  评论(0编辑  收藏  举报