1.不帶參數的function decorator
def add_log(func):
def newFunc(*args, **kwargs):
logger.debug("Before %s() call" % func.__name__)
res = func(*args, **kwargs)
logger.debug("After %s() call" % func.__name__)
return res
return newFunc
@add_log
def funcA():
print "In funcA"
@add_log
def funcC(x, y):
print x + y
funcA()
funcC(2, y=3)
@second
@first
def func():
print('test')
func()
2.帶參數的function decorator
import time
def add_log(logger, timeFormat="%b %d %Y - %H:%M:%S"):
def decorator(func):
def newFunc(*args, **kwargs):
logger.debug("Start {0} call on {1}".format(func.__name__, time.strftime(timeFormat)))
res = func(*args, **kwargs)
logger.debug("Finish {0} call on {1}".format(func.__name__, time.strftime(timeFormat)))
return res
return newFunc
return decorator
@add_log(logger)
def funcA():
print("In funcA")
@add_log(logger, timeFormat="%m-%d-%Y %H:%M:%S")
def funcB():
print("In funcA")
funcA()
funcB()
3.保留__name__、__doc__
from functools import wraps
def add_log(logger, timeFormat="%b %d %Y - %H:%M:%S"):
def decorator(func):
@wraps(func) # 透過functools的wraps函數,參數是傳入的func
def newFunc(*args, **kwargs):
logger.debug("Start {0} call on {1}".format(func.__name__, time.strftime(timeFormat)))
res = func(*args, **kwargs)
logger.debug("Finish {0} call on {1}".format(func.__name__, time.strftime(timeFormat)))
return res
return newFunc
return decorator
@add_log(logger)
def funcA():
print("In funcA")
print(funcA.__name__)
4.class decorator
import logging
from functools import wraps
import time
LOG_FILE = "test.log"
logging.basicConfig(filename = LOG_FILE, level = logging.DEBUG)
def add_log(logger, timeFormat = "%b %d %Y - %H:%M:%S"):
def decorator(func):
if hasattr(func, "_logger_added") and func._logger_added:
return func
@wraps(func)
def newFunc(*args, **kwargs):
logger.debug("Start {0} call on {1}".format(func.__name__, time.strftime(timeFormat)))
res = func(*args, **kwargs)
logger.debug("Finish {0} call on {1}".format(func.__name__, time.strftime(timeFormat)))
return res
newFunc._logger_added = True
return newFunc
return decorator
def log_methods(timeFormat = "%b %d %Y - %H:%M:%S"):
def decorator(clz):
logger = logging.getLogger(clz.__name__)
for member_name in dir(clz):
if member_name.startswith("__"):
continue
member = getattr(clz, member_name)
if hasattr(member, "__call__"):
decorated_func = add_log(logger, timeFormat)(member)
setattr(clz, member_name, decorated_func)
return clz
return decorator
@log_methods()
class ClassA(object):
def test1(self):
print "test1"
@log_methods(timeFormat = "%m-%d-%Y %H:%M:%S")
class ClassB(ClassA):
def test1(self):
super(ClassB, self).test1()
print "child test1"
def test2(self):
print "test2"
obj1 = ClassA()
obj2 = ClassB()
obj1.test1()
obj2.test1()
obj2.test2()