函数(闭包函数,装饰器)
闭包函数
1.什么是闭包函数。
定义在函数内部的函数,这个内部函数引用了外部函数变量。
2.为什么要用闭包函数。
保存局部信息不被销毁,保证数据的安全性
3.怎么使用闭包。
例子:
# 例一: def wrapper(): a = 1 def inner(): print(a) return inner ret = wrapper() # 例二: a = 2 def wrapper(): def inner(): print(a) return inner ret = wrapper() # 例三: def wrapper(a,b): def inner(): print(a) print(b) return inner a = 2 b = 3 ret = wrapper(a,b)
这三个例子都是闭包函数
给函数传参数值有两种方式:
1.普通的传参
def index1(username): print(username)
2.闭包
def outter(x,y): def my_max(): if x>y: return x return y return my_max res =outter(1,40) res1 = outter(10,3)
4.那么闭包函数可以做哪些事情呢?
1.可以保存一些非全局变量但不易被销毁,改变的数据
2.装饰器
下面我们就引入了装饰器
装饰器
1.什么是装饰器。
就是给被装饰对象加上新的功能。在不改变原被装饰的函数的源代码以及调用方式下,为其添加额外的功能。
2.为什么要使用装饰器。
这里我们要解释一个新名词,开放封闭原则。
开放封闭原则:
开放:对扩展开放
封闭:对修改封闭
3.如何使用装饰器
首先我们按照之前的知识写一下,统计index函数执行的时间
import time def index(): time.sleep(3) print('index.....') start = time.time() index() end = time.time() print('index 执行了%s' %(end-start))
修改一下上面代码,将统计时间用函数包装一下。装饰器简单版本
import time def index(): time.sleep(3) print('index..................') def outtere(func): def get_time(): start = time.time() func() end = time.time() print('run time:%s',%(end-start)) return get_time index = outter(index) index()
如果我们的Index函数有参数呢,我们可以继续改进一下(无参函数和有参函数都可以直接调用,可以接收任意数量的参数)
import time def index(name): time.sleep(3) print('%s hello' %name) def outter(func): def get_time(*args,**kwargs): start = time.time() res = func(*args,**kwargs) end = time.time() print('run time:%s'%(end-start)) return res return get_time index = outter(index) index('zzp')
index = outter(index)这句话是不是我们每次在装饰函数时都要这样写?现在有一种很简便的写法
语法糖在书写的时候应该与被装饰对象紧紧挨着
两者之间不要有空格
import time def outter(func): def get_time(*args,**kwargs): start = time.time() res = func(*args,**kwargs) end = time.time() print('run time:%s'%(end-start)) return res return get_time @outter #index = outter(index) def index(name): time.sleep(3) print('%s hello' %name) index('zzp')
装饰器的模板
def outter(func): def inner(*args,**kwargs): print('执行被装饰函数之前 你可以做的操作') res = func(*args,**kwargs) print('执行被装饰函数之后 你可以做的操作') return res return inner
带参数的装饰器
def login_auth2(data_source): # data_source = 'file' def login_auth(func): # func = index 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>>>:').strip() password = input('please input your password>>>:').strip() 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')
def index():
print('.....')
index()
这里的@login_auth2('file') 相当于 index = login_auth(index)
叠加多个装饰器(**)
1.加载顺序(outter函数的调用顺序)自下而上
2.执行顺序(wrapper函数的执行顺序)自上而下
def outter1(func1): #func1=wrapper2的内存地址 print('加载了outter1') def wrapper1(*args,**kwargs): print('执行了wrapper1') res1=func1(*args,**kwargs) return res1 return wrapper1 def outter2(func2): #func2=wrapper3的内存地址 print('加载了outter2') def wrapper2(*args,**kwargs): print('执行了wrapper2') res2=func2(*args,**kwargs) return res2 return wrapper2 def outter3(func3): # func3=最原始的那个index的内存地址 print('加载了outter3') def wrapper3(*args,**kwargs): print('执行了wrapper3') res3=func3(*args,**kwargs) return res3 return wrapper3 @outter1 # outter1(wrapper2的内存地址)======>index=wrapper1的内存地址 @outter2 # outter2(wrapper3的内存地址)======>wrapper2的内存地址 @outter3 # outter3(最原始的那个index的内存地址)===>wrapper3的内存地址 def index(): print('from index') index()
万般皆下品,唯有读书高!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!