python之装饰器

装饰器的概念

  • 装饰器的实现是函数里面嵌套函数;
  • 装饰器的本质是一个函数, 它可以让其他函数在不需要做任何代码改动的前提下增加额外的功能,即想要增强原有函数的功能,但不希望修改now()函数的定义;
  • 装饰器需要传递一个函数, 返回值也是一个函数对象.
    eg:在程序执行之前写祝福语,在程序执行之后打广告:
def desc(fun):                    #1).  需要传递一个函数, 要装饰的函数   fun=login()
    def add_info():               # 2). 装饰器函数里面嵌套函数
        print("祝您幸福!")
        fun()                       # login()
        print("欢迎再次使用")
    return add_info             #3). 返回值是嵌套的函数对象

# 语法糖
@desc   # login = desc(login)    # 4). 如何调用装饰器(两种方式),返回值是一个函数。
def login():
    print("login......")
login()                           #此时的login()是add_info()

这里写图片描述

装饰器的应用场景

  • 计时器
import time

def timeit(fun):                    #fun=add()
    def wrapper(*args, **kwargs):   # 接收可变参数和关键字参数
        # args: 元组   kwargs: 字典
        # 函数执行之前
        start_time = time.time()
        # 执行函数
        res=fun(*args, **kwargs)            # 对于元组解包, 对于字典解包,并且将add的返回值给res
        # 执行函数之后
        end_time = time.time()
        print("运行时间为:%.6f" % (end_time - start_time))
        return res
    return  wrapper
@timeit
def add(a,b):
    time.sleep(3)
    return a+b
print(add(1,3))        #实际执行wrapper,并把wrapper的返回值打印

这里写图片描述

  • 记录日志
import functools
import time
def add_log(fun):
    @functools.wraps(fun)                #可以保留被装饰函数名和帮助文档信息
    def wrapper(*args, **kwargs):
        run_time = time.ctime()          #日志的时间
        fun_name = fun.__name__          #函数名称
        start_time = time.time()
        res = fun(*args, **kwargs)
        end_time = time.time()
        print("[%s] 函数名: %s, 运行时间:%.5f, 运行返回值结果:%d"
              %(run_time, fun_name, end_time-start_time, res )
              )
        return res
    return wrapper

@add_log
def add(x,y):
    '''
    这是求和函数
    '''
    time.sleep(0.1)
    return x+y
print(add(1,2))
print(add.__doc__)

这里写图片描述

  • 用户登陆验证
import functools
login_users = ['admin', 'root']
def is_login(fun):                          # fun: writeBlog
    @functools.wraps(fun)
    def wrapper(*args, **kwargs):          # name="admin"  # kwargs={"name":"admin"}
        # 判断写博客的这个用户是否登陆成功;
        if kwargs.get("name") in login_users:
            res = fun(*args, **kwargs)
            return res
        else:                       #如果没有登陆成功,就跳转到登陆界面
            res=login()
        return res

    return wrapper

# 必须登陆成功
@is_login    # writeBlog = is_login(writeBlog)
def writeBlog(name):
    return "编写博客"
def login():
    return "登陆。。。。"
# 是否登陆成功都可以执行代码
def news():
    print("新闻......")
print(writeBlog(name="admin1"))

这里写图片描述

  • 函数参数验证
import functools
def required_ints(fun):
    @functools.wraps(fun)
    def wrapper(*args, **kwargs):         # args=(1,2)
        for i in args:
            if not isinstance(i , int):
                print("函数所有参数并非为整形")
                break
        else:
            res = fun(*args, **kwargs)
            return  res
    return wrapper

@required_ints
def add(a, b):
    return a + b
print(add(1,2))

这里写图片描述

带有多个装饰器的函数

  • 当有多个装饰器时, 从下到上调用装饰器,
  • 真实wrapper内容执行是从上到下执行.
    eg:
def makebold(fun):
    print("bold1")
    def wrapper1(*args, **kwargs):
        print("bold2")
        return  fun(*args, **kwargs)  # wrapper
    return  wrapper1

def makei(fun):   # fun=login
    print("i1")
    def wrapper(*args, **kwargs):
        print("i2")
        return  fun(*args, **kwargs)
    return  wrapper

@makebold  # login = makebold(login)   # login为wrapper1
@makei    # login = makei(login)    # login为wrapper
def login():
    return "登陆"
print(login())

这里写图片描述

带有参数的装饰器

import functools
import time
def log(kind):                 # kind="debug"   kind为参数
    def add_log(fun):
        @functools.wraps(fun)
        def wrapper(*args, **kwargs):
            start_time = time.time()
            res = fun(*args, **kwargs)
            end_time = time.time()
            print("<%s> [%s] 函数名: %s, 运行时间:%.5f, 运行返回值结果:%d"
                  %(kind, time.ctime(), fun.__name__, end_time-start_time, res )
                  )
            return res
        return wrapper
    return  add_log
@log("debug")
#  log("debug")==> 返回值是add_log
#  add=add_log(add)
def add(x,y):
    time.sleep(0.1)
    return x+y
add(1,2)

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值