python---装饰器

概念

装饰器就是一个可以接受调用也可以返回调用的函数,该函数接受被装饰的函数作为其位置参数。 装饰器通过使用该参数来执行某些操作,然后返回原始参数或一些其他的调用

本质

装饰器可以让函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。

因此定义装饰器的本质就是一个函数,只不过这个函数的功能是用来为其他函数添加额外的功能。

带参数的装饰器和不带参数的装饰器

不带参数的装饰器是普通的装饰器,需要两层函数。
带参数的装饰器可以看成是装饰器工厂,需要三层函数,因为要传递装饰器的参数,所以多了一层函数。

装饰器的简单使用:

不带参数的装饰器:

###定义装饰器
def check(func):
    print("验证权限")
    def inner(identify):
        func(identify)
    return inner

###装饰装饰器
@check
def f1(user_id):
    if user_id=="root":
        print("允许root用户操作")
    else:
        print(f"不允许{user_id}用户操作")

f1("root")

运行结果:
在这里插入图片描述

带参数的装饰器:

def deco(arg):
    def inner1(func):
        def _cost(a,b):
            func(a,b)
            print(f"装饰器的参数是{arg}")
        return _cost
    return inner1

@deco(1)
def fun1(a,b):
    print(f"我是真正的函数体,{a}+{b}={a+b}")
fun1(1,3)

运行结果为:
在这里插入图片描述
这里可以看到,最外面的一层函数其参数是@deco(1)中的参数1,inner函数的参数是装饰器装饰的函数的引用,这里是fun1,最里面的函数的参数是func1函数的参数即1,3

作用/优点

装饰器最大的作用就是用来包装代码块,让其具有特定的功能。

装饰器有以下优点:
• 模块化且清晰明确

• 代码重用

• 装饰器是显式的,增强可读性

多个装饰器的顺序

当有两个装饰器来装饰用一个函数的时候。离函数近的装饰器先进行装饰,装饰器先装饰完后将整个装饰结果给第一个装饰器进行装饰

即常说的:封装时自内而外(自下而上),执行时自外而内(自上而下)

###实现多重装饰,先验证有没有登录,再验证权限够不够
def login_required(func):
	print("开始权限的验证")
    def inner(username,passwd):
        if username=="root":
            result=func(username,passwd)
            return result
        else:
            print("权限不够")
            exit(0)
    return inner

def login_valid(func):
	print("开始用户登录的验证")
    def inner(username,passwd):
        if passwd==123456:
            print("用户登录成功!")
            func(username,passwd)
            return True
        else:
            print("密码错误")
            return False
    return inner

@login_valid    ##验证登录是否成功
@login_required   #验证有没有权限
def login(username,passwd):
    print("欢迎root用户")
login("root",123456)

运行结果为:
在这里插入图片描述
可以看到结果封装的时候是从下向上进行封装的,,但是执行的时候是先判断登录再判断权限,因次执行时是自上而下的顺序

使用例子

日志

import time
def input_log(name):
    import logging
    ###获取logger对象
    logger = logging.getLogger()  ###提供日志文件可使用的接口,直接获取的是root logger  (不取名的是默认logger对象)
    # logger=logging.getLoger("name")   则会创建名为name的logger对象。继承root logger对象,root logger对象相当于是对整个logger的配置。然后声明子对象,继承root logger。在配置好的环境之上进行操作
    ##创建Handler
    fh = logging.FileHandler("test2.log",encoding="utf-8")  ##创建一个输出到指定test.log文件的Handler
    ch = logging.StreamHandler()  ##创建一个输出到控制台的Handler

    ##创建一个formatter的日志格式
    formatter = logging.Formatter(
        "%(asctime)s - %(name)s - %(levelname)s - %(message)s")  # 格式为时间-当前logger的对象名-运行的日志等级-日志信息
    ##绑定formatter到Handler上
    fh.setFormatter(formatter)  ###设置文件输出对象的格式

    ##绑定handler到logger上
    logger.handlers.clear()   #清空绑定的handler对象
    logger.addHandler(fh)
    logger.addHandler(ch)

    # logging.basicConfig(level=logging.DEBUG)   ##设置的是logging的函数的等级
    logger.setLevel(level=logging.DEBUG)
    logger.debug(f"执行了{name.__name__}函数")    ###name.__name__获得当前的函数名
    logger.info("logger info message")
    logger.warning("this is warning message")
    logger.error("this is error message")
    logger.critical("this is critical message")

def log(func):
    print("log")
    def inner(b):
        a=func(b)
        input_log(func)
        return a
    return inner

@log
def fun2(a):
    b=a+2
    time.sleep(1)
    print("func2 result:",b)
    return b
fun2(2)

运行结果:
在这里插入图片描述

装饰器实现类对象按照创建时间排序

import functools
import time
####定义按创建时间排序的装饰器
def sortable_by_create_time(cls):
    original_init=cls.__init__
    @functools.wraps(original_init)
    def new_init(self,*args,**kwargs):
        original_init(self,*args,**kwargs)
        self.create_time=time.time()

    cls.__init__=new_init
    cls.__lt__=lambda self,other:self.create_time<other.create_time
    return cls

@sortable_by_create_time
#####创建一个类
class Sortable():
    def __init__(self,identifier):   ##初始化对象
        self.identifier=identifier
        self.create_time=time.time()

    def __repr__(self):   ###返回对象的说明信息
        return self.identifier   
yy=Sortable("yy")
time.sleep(0.1)
first=Sortable("first")
time.sleep(0.1)
second=Sortable("second")
time.sleep(0.1)
third=Sortable("third")

result=[first,second,third,yy]
print(sorted(result))   #sorted会自动去找类对象排序的行为

运行结果:
在这里插入图片描述

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值