闭包函数
什么叫做函数的闭包 闭包其实就是函数的嵌套 定义在函数的内部 且内部函数用了外部函数名称空间作为名字 从而达到闭包 (函数在定义阶段的时候 他的名称空间查找顺序就已经固定的 不会因为 你的调用位置的改变而改变)
以上就是一个闭包函数 他是先定义 outer函数 然后 a=outer() 因为这里的outer加了()号 所以 他就直接执行了函数outer 同样 它里面的函数不调用是不会执行的 最后一个返回值 inner 这个返回值他会直接给a 因为赋值了 当a加()的时候等价于 inner() 因为a的地址现在指向inner 最后执行print(name) 因为本层没有 就去上层找 发现有就执行了.
闭包还可以这样传参
装饰器
引入问题: 定义了一个函数,想在运行时动态的增加功能,又不想改动函数本身的代码?
装饰器其实就是一个工具 可以给其他函数添加功能 但是必须要 不能改变原函数的代码 且 不能改变函数的调用方式 开发封闭原则 对扩展开发 对修改关闭.
如何定义一个装饰器?装饰器分为两种 第一是有参装饰器 有参就是func内可以传入参数
第二是无参装饰器 就是func内不可传入参数
"""假如说我们想对下面的函数添加功能但是又不能改变他的代码 和调用方式怎么办呢""" def login(): print('登录成功') 我们可以使用闭包来写 def outer(func): #这里的func我们来传login的调用方式 def inner(*args,**kwargs): #这里就可以来写他的 添加功能了 假如我们来写一个登录功能 user_name=input('请登录:').strip() if user_name != '': res=func(*args,**kwargs)
return res return inner login=outer(login) 这里的login不是函数名 指向的地址是inner login()
这样的一个装饰器我们就写好了
运行流程: 加载 login函数 加载 def outer函数
运行outer(login)因为 ()在代码中执行权最高 里面的inner读到func 里的地址 保存下来
但是没有执行 然后执行return 把inner的地址返回并赋值给login 现在调用login() 就等于执行了 inner()
然后执行里面你添加的代码 最后读到func()的时候执行 login
因为现在的这个func指向的地址就是当初你传进来的那个 login的地址 现在加了括号就可以直接运行了.
这段代码还可以优化 就是加装饰器语法糖@
例如
def outer(func): def inner(*args,**kwargs): user_name=input("输入账号").strip() if user_name != '': res=func(*args,kwargs) return res return inner @outter 这个语法糖相等于 login=outer(login) 这样你使用就可以直接调用了 不需要再写了 提升 他只会找离自己最近的那个:会将紧挨着它的可调用对象的名字当做参数自动传入调用outter def login (name): print('登录成功') print('欢迎',name)
但是他最后调用的那个login() 他的地址其实是指向 inner 因为他只是覆盖了名字 地址却没有改变 那么怎么办呢
python自带一个 模块可以处理这个问题 装饰器修复技术 可以返回原来的函数名 返回原来函数的注释
from functools import wraps #这个就是那个模块了 用的时候 在第二层写@wraps def outter(func): @wraps(func) def inner(*args,**kwargs): # * **在形参中使用 # 执行被装饰函数之前你可以做的操作 res = func(*args,**kwargs) # * **在实参中使用 # 执行被装饰函数之后你可以做到操作 return res return inner @outter def index(username,*args,**kwargs): """index注释""" pass print(index)
多层装饰器
总结
1 要想装饰器不修改被装饰函数的返回值,我们需要在装饰器中接受被装饰函数的返回值并Return即可。
2 如果希望对被装饰函数进行分类处理,我们可以在绑定装饰器时传入一个参数用于对被装饰函数进行分类,但是这样我们需要在装饰器中在套一层函数,在第一层接收装饰器传递的参数,在第二层函数中接收被装饰函数。
3 如果希望装饰器既能装饰带参的函数也可以修饰不带参的函数,我们只需要在装饰器中接收参数时,把参数定义为非固定参数即可。