6.装饰器
一、闭包
1.1 什么是闭包?
闭包有什么作用。
- 闭包只能存在嵌套函数中。
- 内层函数对外层函数非全局变量的引用(使用),就会形成闭包。
被引用的非全局变量也称作自由变量,这个自由变量会与内层函数产生一个绑定关系,自由变量不会再内存中消失。
闭包的作用:保证数据的安全。
闭包的应用:
- 可以保存一些非全局变量但是不易被销毁、改变的数据。
- 装饰器。
如何判断一个嵌套函数是不是闭包?
- 闭包只能存在嵌套函数中。
- 内层函数对外层函数非全局变量的引用(使用),就会形成闭包。
二、装饰器
开放封闭原则:
-
开放:对代码的拓展
-
封闭:对源码的修改是封闭的,源代码不应该被修改,如已经实现的的函数等
-
装饰器:在不改变原函数的代码以及调用方式的前提下,为其增加新的功能
-
装饰器就是一个函数
装饰器
在代码运行期间动态增加功能的方式。
# 用户可以直接登录
def home():
login()
print('首页')
def movie():
print('电影')
现在要做登录验证:
def login():
print('登录验证')
def home():
login() # 这里做了登录验证
print('首页')
def movie():
print('电影')
在home函数中做了登录验证,但是破坏了开放封闭原则,改变了原来写好的代码
def login(func):
print('登录验证')
func()
def home():
print('首页')
def movie():
print('电影')
home()
login(movie)
以上改写也不好,修改了调用方式,需要认证的模块都需要修改调用方式。需要不改变原功能代码,又不改变原有调用方式,还能加上认证的代码改写。
def login(func):
print('登录验证')
func()
return
def home():
print('首页')
def movie():
print('电影')
home()
lo = login(movie)
lo()
这里不改变函数的调用方式,也不违反开放--封闭原则,但是lo = login(movie)就会执行movie()函数,可以在外面再嵌套一层,使lo = login(movie)只调用外层函数,不执行movie()函数。
def login(func):
def inner():
print('登录验证')
func()
return inner
def home():
print('首页')
def movie():
print('电影')
home()
lo = login(movie)
lo()
这样就间接调用movie()函数了,lo = login(movie)改写为@login,
def login(func):
def inner():
print('登录验证')
func()
return inner
def home():
print('首页')
@login
def movie():
print('电影')
home()
movie() # 等同于lo = login(movie)
定义一个能打印时间的装饰器
import datetime
def log(func): # 装饰器接受一个函数作为参数,并返回一个函数名
def wrapper(*args, **kwargs):
print('call %s(): ' % func.__name__)
return func(*args, **kwargs)
return wrapper
@log # 运用@语法把装饰器放置在函数定义处
def now():
print(datetime.datetime.now())
now()
"""
call now():
2020-07-06 21:56:43.968471
"""
带参数的装饰器
def login(func):
def inner(*args, **kwargs):
print('登录')
func(*args,**kwargs)
return inner
@login
def funca(name):
print('欢迎', name)
funca('asdw')
# 登录
# 欢迎 asdw
# 装饰器加参数
def logger(path):
def log(func):
def inner(*args, **kwargs):
ret = func(*args, **kwargs)
with open(path, encoding='utf-8', mode='wt')as f1:
f1.write('%s 执行了%s'%(time.strftime('%Y-%m-%d %H:%M:%S'), func.__name__))
return ret
return inner
return log
@logger('auth.log')
def login():
print('登录')
@logger('auth.log')
def register():
print('注册')
@logger('auth.log')
def show_goods():
print('查看商品信息')
@logger('operate.log')
def add_goods():
print('购物车')
login()
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗