欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 创投人物 > python语言基础-5 进阶语法-5.2 装饰器-5.2.4 装饰器类

python语言基础-5 进阶语法-5.2 装饰器-5.2.4 装饰器类

2025/5/21 6:30:53 来源:https://blog.csdn.net/qq_29567799/article/details/143895595  浏览:    关键词:python语言基础-5 进阶语法-5.2 装饰器-5.2.4 装饰器类

声明:本内容非盈利性质,也不支持任何组织或个人将其用作盈利用途。本内容来源于参考书或网站,会尽量附上原文链接,并鼓励大家看原文。侵删。

5.2.4 装饰器类

(1)创建一个装饰器类

在python中一切皆对象,函数也是对象。而前面我们都使用嵌套函数的方式来定义装饰器(称为函数装饰器),下面我们将学习使用类来定义一个装饰器(称为类装饰器)。

定义一个打印日志的类装饰器:

from functools import wraps# 创建一个装饰器类
class logit(object):def __init__(self, logfile='out.log'):  # 如果要创建带参数的装饰器,可以在初始化方法中添加参数self.logfile = logfiledef __call__(self, func):  # __call__魔术方法的触发时机是将对象当作函数调用时触发,而下面将logit当作装饰器使用,就是将被装饰函数作为参数,将logit对象当作了函数@wraps(func)def wrapped_function(*args, **kwargs):log_string = func.__name__ + " was called"print(log_string)with open(self.logfile, 'a') as opened_file:  # 现在将日志打到指定的文件opened_file.write(log_string + '\n')self.notify()  # 现在,发送一个通知return func(*args, **kwargs)return wrapped_functiondef notify(self):# logit只打日志,不做别的,因此这里不做实现pass@logit()  # 使用类装饰器,执行的是__call__魔术方法中的逻辑
def myfunc1():passmyfunc1()

由此可见,只要一个类中定义了__call__方法,并且其以内层函数作为返回值,则这个类就是一个装饰器。作为装饰器的类,称为装饰器类。

(2)装饰器类的继承

类装饰器与函数装饰器相比一个重要的优点就是可以继承。

接(1)中的例子,如果我们在打印日志到文件的同时,还想将日志发送到email。我们可以直接使用继承的方式实现,而不需要完全重写一个新的类装饰器。如下:

# 定义一个类装饰器它继承了另一个类装饰器
class email_logit(logit):def __init__(self, email='admin@myproject.com', *args, **kwargs):self.email = emailsuper(email_logit, self).__init__(*args, **kwargs)def notify(self):# 发送一封email到self.email(具体发送email的代码这里就不做实现了)pass# 父类logit中已经实现了__call__魔术方法,子类中我们不需要再次实现
# 父类中的notify()方法不做实现,子类中我们可以重写这个方法,在其中添加发送email的功能

可以看到,如果装饰器需要复合多种功能时,使用类装饰器要比函数装饰器简洁,因为类装饰器可以使用继承。

(3)多层装饰

在学习了类装饰器后,我们知道,可以将多个功能通过继承集中给一个装饰器。那么,我们可以直接在函数上使用多层装饰器吗?答案是肯定的,因为在带参装饰器中我们已经知道函数是可以嵌套的。

#使用多层装饰器
@zhuang3
@zhuang2
@zhuang1
def fang():...#调用原函数
fang()

当使用了多层装饰器时,离原函数越近的装饰器越先被使用。因此,使用有些装饰器时,会有要求其在最外层,例如前面方法重载时,@singledispatchmethod就被要求在其他装饰器之上。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词