Files
python3-cookbook/cookbook/c09/p05_adjust_attribute.py
2015-02-10 14:01:50 +08:00

118 lines
2.4 KiB
Python

#!/usr/bin/env python
# -*- encoding: utf-8 -*-
"""
Topic: 可调整属性的装饰器
Desc :
"""
from functools import wraps, partial
import logging
import time
# Utility decorator to attach a function as an attribute of obj
def attach_wrapper(obj, func=None):
if func is None:
return partial(attach_wrapper, obj)
setattr(obj, func.__name__, func)
# return func
def logged(level, name=None, message=None):
"""
Add logging to a function. level is the logging
level, name is the logger name, and message is the
log message. If name and message aren't specified,
they default to the function's module and name.
"""
def decorate(func):
logname = name if name else func.__module__
log = logging.getLogger(logname)
logmsg = message if message else func.__name__
@wraps(func)
def wrapper(*args, **kwargs):
log.log(level, logmsg)
return func(*args, **kwargs)
# Attach setter functions
@attach_wrapper(wrapper)
def set_level(newlevel):
nonlocal level
level = newlevel
@attach_wrapper(wrapper)
def set_message(newmsg):
nonlocal logmsg
logmsg = newmsg
return wrapper
return decorate
# Example use
@logged(logging.DEBUG)
def add(x, y):
return x + y
@logged(logging.CRITICAL, 'example')
def spam():
print('Spam!')
logging.basicConfig(level=logging.DEBUG)
add(2, 3)
add.set_message('Add called')
add(2, 3)
add.set_level(logging.WARNING)
add(2, 3)
print('---------------------')
spam()
spam.set_message('Add called')
spam()
spam.set_level(logging.WARNING)
spam()
def timethis(func):
"""
Decorator that reports the execution time.
"""
@wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(func.__name__, end - start)
return result
return wrapper
@logged(logging.DEBUG)
@timethis
def countdown(n):
while n > 0:
n -= 1
countdown(10000000)
countdown.set_level(logging.WARNING)
countdown.set_message("Counting down to zero")
countdown(10000000)
@timethis
@logged(logging.DEBUG)
def countdown1(n):
while n > 0:
n -= 1
print('****************************************')
countdown1(10000000)
countdown1.set_level(logging.WARNING)
countdown1.set_message("Counting down to zero")
countdown1(10000000)