暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

python学习——创建可以在运行期间修改属性的装饰器

大鑫笔记 2021-09-10
694


代码源自《python cookbook》一书9.5章节,为了学习理解这部分代码,增加了注释说明

from functools import wraps, partial
import logging

def attach_wrapper(obj, func=None):
'''该方法的主要目的是为obj对象添加ok
添加的属性名称为:func.__name__
添加的属性值为: func
'''

if func is None:
# 效果等同于返回attach_wrapper方法,该方法的第一个参数为obj
return partial(attach_wrapper, obj)
# 为obj对象添加属性,属性名为func.__name__,属性值为func
setattr(obj, func.__name__, func)
return func

def logged(level, name=None, message=None):
'''
该装饰器为方法添加日志信息。
level为日志级别
name为日志名称,不指定则默认为方法所在的模块名称
message为日志内容,不指定则默认为方法名
'''

def decorate(func):
logname = name if name else func.__module__
logmsg = message if message else func.__name__
# 设置日志的默认格式 level:name:message
logging.basicConfig()
log = logging.getLogger(logname)

@wraps(func) # 保留被装饰方法func的元属性不变
def wrapper(*args, **kwargs):
log.log(level, logmsg) # 该语句是装饰func方法的目的,打印日志
return func(*args, **kwargs)

# 为wrapper对象添加set_level方法,做到可以动态设置日志级别
@attach_wrapper(wrapper)
def set_level(newlevel):
# nonlocal修饰的变量可以视为在logged方法内部都是可识别的,
# 而不只是在set_level方法内才有效
nonlocal level
level = newlevel

# 为wrapper对象添加set_message方法,做到可以动态设置日志信息
@attach_wrapper(wrapper)
def set_message(newmsg):
nonlocal logmsg
logmsg = newmsg

return wrapper
return decorate

# logged装饰器使用示例
@logged(logging.DEBUG)
def add(x, y):
return x + y

@logged(logging.CRITICAL, 'example')
def spam():
print('Spam!')

if __name__ == "__main__":
# 1. 展示add、spam装饰默认的日志级别level和日志信息message
add(2, 3) # 不打印任何信息,因为logging模块默认不输出DEBUG级别的日志
spam() # CRITICAL:example:spam
# 2. 展示运行期间,修改日志级别level和日志信息message
add.set_message("调用add方法")
add.set_level(logging.ERROR)
add(2,3) # ERROR:__main__:调用add方法

spam.set_message("调用spam方法")
spam.set_level(logging.WARNING)
spam() # WARNING:example:调用spam方法

文章转载自大鑫笔记,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论