函数装饰器
装饰器作用
下面为两个函数增加检查登录功能的代码,方法1需要每个函数下方都添加过于繁琐,方法2调用方式改变,在项目时不希望改变已成功实现的代码(因为可能是借鉴来的不敢修改,不想改变代码的调用方式,
想要解决此类问题可以使用装饰器,装饰器提供了高效,简洁的实现方法
# 方法1 直接在函数内修改
def f1():
print('check login')
print('f1')
def f2():
print('check login')
print('f2')
#调用
f1()
f2()
# 方法2 添加检查登录的函数
def logincheck(func):
print('check login')
func()
def f1():
print('f1')
def f2():
print('f2')
#调用
logincheck(f1)
logincheck(f2)
函数装饰器
# 形成闭包,装饰器
def logincheck(func):
def wrapper():
print('check login')
return func()
return wrapper
def f1():
print('f1')
#调用
f1 = logincheck(f1)
f1()
# 使用@
def logincheck(func):
def wrapper():
print('check login')
return func()
return wrapper
@logincheck
def f1():
print('f1')
#调用
f1()
#结果一致
check login
f1
@logincheck相当于f1 = logincheck(f1)作用,logincheck函数返回一个函数,相当于 wrapper = f1
调用函数有参数时,装饰器如何改变
def logincheck(func):
def wrapper(x):
print('check login')
return func(x)
return wrapper
@logincheck
def f1(x):
print('f1',x)
#调用
f1('python')
#返回值
check login
f1 python
传入多个参数时使用*args(元组),**kwargs(关键字参数)
def logincheck(func):
def wrapper(*args):
print('check login')
return func(*args)
return wrapper
@logincheck
def f1(x,y):
print('f1',x,y)
#调用
f1('hello','python')
#返回值
check login
f1 hello python
当传入多个参数时对应改变wrapper内的参数即可
当装饰器存在参数时
def loginname(per):
def logincheck(func):
def wrapper():
print(per,'check login')
return func()
return wrapper
return logincheck
@loginname('x')
def f1()
print('f1')
f1()
#返回
x check login
f1
@loginname('x') = loginname('x')(f1),先函数loginname('x')返回logincheck,随后调用形式为logincheck(f1)返回wrapper,wrapper=f1,调用f1()=wrapper(),返回结果
_ _name _ _
__name__作用
内置函数,可以观察到模块是自己执行还是被调用
#模块名为nameScript.py
def myFunction():
print('变量 __name__ 的值是 ' + __name__)
def main():
myFunction()
if __name__ == '__main__':
main()
输出:变量 __name__ 的值是 __main__
# 自己直接执行代码时 __name__ 的值是 __main__
# 导入模块
import nameScript as ns
ns.myFunction()
输出:变量 __name__ 的值是 nameScript
# 调用模块时 __name__ 的值是被调用模块的名字
def logincheck(func):
def wrapper():
print('check login')
return func()
return wrapper
@logincheck
def f1():
print('f1')
print(f1.__name__)
# 输出wrapper
上述装饰器可以看到f1.__name__的信息被修改为wrapper,我们希望在简介代码的同时不丢失原函数的信息,希望f1.__name__的值为f1,使用functools.wraps来解决这一问题,,wraps本身也是一个装饰器,它能把原函数的元信息拷贝到装饰器里面的 func 函数中,这使得装饰器里面的 func 函数也有和原函数一样的元信息了
from functools import wraps
def logincheck(func):
@wraps(func) #在与原函数有同样功能的函数前添加
def wrapper():
print('check login')
return func()
return wrapper
@logincheck
def f1():
print('f1')
print(f1.__name__)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了