python装饰器(一)

 装饰器介绍:

#装饰器:是一种程序设计模式,主要用于给函数添加一些额外功能(比如统计函数运行时间等)
#      又不希望通过继承或者修改源代码的方式去实现,就使用装饰器
#将要添加功能的函数作为内函数,将功能加在外函数内和内函数外

#装饰器本质是闭包,它需要把一个callable对象作为参数传递进来
#callable对象包含函数
import time
# def func1():
#     print("I am func1")
#     outer_time = time.time()
#     time.sleep(1)
#     def func2():
#         print("I am func2")
#         inner_time=time.time()
#         print(inner_time-outer_time)
#     return func2
#
# start=time.time()
# f=func1()
# f()
# end=time.time()
# print(f"运行花了{end-start}s")


# #使用装饰器
# def runtime(func):#func作为外函数给内函数的传值 √
#     def inner():
#         start = time.time()
#         result=func()
#         end = time.time()
#         print(f"执行{func.__name__}花费了{end-start}")
#         return result#将被加过功能(装饰)的传入函数作为内函数的返回值
#     return inner# 返回内函数 √
# # @是修饰符,一般用于装饰器 语法糖
# @runtime  #fun2=runtime(func2)
# #表示使用runtime装饰器,
# # 相当于将func2作为runtime的传值再将经过修饰器修改后的函数传回赋值给func2执行
# #最后运行的func2是装饰器中的inner函数
# def func2():
#     time.sleep(2)
#     print("I am func2")
# func2()#就是运行inner函数,可断点调试查看过程

# @runtime #需要装饰器中加的功能就加@runtime,不用就不加
# def func3():
#     time.sleep(3)
#     print("I am func3")
# func3()
# print(f"函数名:{func3.__name__}")
# #输出结果为inner,表面确实最后执行函数为inner而不是func3

# #写一个装饰器,进行日志记录
# import logging
# def log(func):
#     def inner():
#         logger = logging.getLogger()
#         # 处理器,决定日志发送到哪里
#         treat = logging.FileHandler("test.log")  # 日志写入文件
#         # 格式器
#         # 定义一个格式
#         Log_format = "%(asctime)s - %(pathname)s:%(lineno)d-%(levelname)s : %(message)s"
#         # 给格式器设定以上格式
#         formatter = logging.Formatter(Log_format)
#         # 为写入文件的处理器treat绑定该种格式器
#         treat.setFormatter(formatter)
#         # 将handler处理器绑定到logger对象(日志器)上
#         logger.addHandler(treat)
#         # 默认情况下只有warning以上的日志才会记录
#         logger.setLevel(logging.DEBUG)  # 开启调试,记录DEBUG等级以上的日志
#         logger.info("function test is used")
#         result=func()
#         return result
#     return inner
# @log
# def test():
#     global x
#     x=100
# test()

#或者:
from logset import logger

def log(func):
    def inner():
        result=func()
        logger.info(f"函数{func.__name__}已经执行")
        return result
    return inner
@log
def test():
    print("i am func 4")
test()

带参数的装饰器:

import time

#不带参数的装饰器,使用两层函数定义
#带参数的装饰器,使用三层函数定义

def deco(flag):
    def runtime(func):
        def inner(*args,**kwargs):
            print(f"带参数的装饰器{flag}")
            start = time.time()
            result = func(*args,**kwargs)
            end=time.time()
            print(f"执行{func.__name__}花费{end-start}s")
            return result
        return inner
    return runtime
# runtime=deco(flag=1)
# func1=runtime(func1)
@deco(flag=1)
def func1():
    print("i am func1")
    time.sleep(2)
func1()

装饰器应用:

#1、权限认证
#2、统计运行时间
#3、日志记录
from logset import logger
import time
from functools import wraps

#运行时间装饰器
def runtime(func):#func作为外函数给内函数的传值 √
    #解决log装饰器在runtime后执行时识别函数为inner的问题
    @wraps(func) #保留元数据,将传进去的func的元数据全部复制給inner
    def inner(*args,**kwargs):
        start = time.time()
        result=func(*args,**kwargs)
        end = time.time()
        print(f"执行{func.__name__}花费了{end-start}")
        return result#将被加过功能(装饰)的传入函数作为内函数的返回值
    return inner# 返回内函数 √

#日志记录装饰器
def log(func):
    def inner(*args,**kwargs):
        result=func(*args,**kwargs)#加上*args,*kwargs,让装饰器更加通用
        #接受可变长位置参数和可变长关键字参数,让装饰器更通用
        logger.info(f"函数{func.__name__}已经执行")
        time.sleep(1)
        return result
    return inner

# #可以应用多个装饰器,但是要注意装饰器的执行顺序
# @runtime #后装饰,这时运行时间包括了log的inner函数时间与test函数的时间,不准确
# @log #先装饰
# def test():
#     print("I am test")
#     time.sleep(2)
# test()
# def test2(a,b):
#     time.sleep(1)
#     return a+b
# result=test2(1,3)
# print(result)

#可以应用多个装饰器,但是要注意装饰器的执行顺序
@log #后装饰,这时log识别的是runtime的inner函数,不准确
@runtime#先装饰  inner=runtime(test)
# 在runtime中用@wraps装饰后就将test元数据(函数名等)传给了runtime的inner
# 这样test的函数名等得以保留到log进行函数识别
def test():
    print("I am test")
    time.sleep(2)
test()
def test2(a,b):
    time.sleep(1)
    return a+b
result=test2(1,3)
print(result)

用类实现装饰器:

import time
class A:
    def __init__(self,func):
        self.func=func
    def __call__(self,*args,**kwargs):
        start = time.time()
        time.sleep(1)
        end = time.time()
        result=self.func(*args,**kwargs)
        print(end-start)
        return result

class B:
    def __init__(self,username):
        self.username=username
    def __call__(self,func):
        def inner(*args,**kwargs):
            start = time.time()
            time.sleep(1)
            end = time.time()
            result=func(*args,**kwargs)
            print(end-start)
            return result
        return inner
# @A
# def func1():
#     print("I am func1")
# func1()

@B("username")
def func2():
    print("I am func2")
func2()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值