函数装饰器

装饰器作用

下面为两个函数增加检查登录功能的代码,方法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__)
posted @   凡凡的宝贝  阅读(33)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示