python 64式: 第5式、装饰器


#!/usr/bin/env python
# -*- coding: utf-8 -*-

from datetime import datetime
import functools
import time

'''
关键:
1 装饰器
含义:代码运行期间动态增加功能
本质:返回函数的高阶函数,接收函数本身作为参数,返回一个包含对该函数前后处理的函数

2 无参装饰器: 
def timeHelper(func):
    def wrapper(*args, **kwargs):
        ...
	func(*args, **kwargs)
	...
    return wrapper

@timeHelper
def run():
    ...
等同于
run = timeHelper(run)

3 有参装饰器:
如果装饰器本身需要传入参数,需要定义三层函数
最外层函数的参数是装饰器本身参数,中间函数的参数是函数对象,
最里面函数的参数是*args,**kwargs
def timeHelperWithParam(text):
    def _wrapper(func):
        def wrapper(*args, **kwargs):
	    ...
	    func(*args, **kwargs)
	    ...
        return wrapper
    return _wrapper

@timeHelperWithParam('function name')
def run():
    ...
等同于
run = timeHelperWithParam('function name')(run)
解释:
timeHelperWithParam('function name')是一个函数类

4 保持函数名称不随装饰器改变
只需要添加:  @functools.wraps(func)
具体用法如下:
def timeHelperWithParam(text):
    @functools.wraps(func)
    def _wrapper(func):
        def wrapper(*args, **kwargs):
	    ...
	    func(*args, **kwargs)
	    ...
        return wrapper
    return _wrapper

参考:
https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/001386819879946007bbf6ad052463ab18034f0254bf355000
'''

def timeHelper(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        try:
            start = datetime.now()
            info = "############ Function name: %s, Starts at: %s ##########" % (
                func.__name__, str(start))
            print info
            func(*args, **kwargs)
            end = datetime.now()
            diff = end - start
            info = "############ Function name: %s, Ends at: %s, cost time: %s ############ " % (
                func.__name__, str(end), str(diff))
            print info
        except Exception as ex:
            info = "Exception type is %s, message is %s" % (ex.__class__.__name__, ex)
            print info
    return wrapper


@timeHelper
def run():
    time.sleep(3)


def timeHelperWithParam(text):
    def _wrapper(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            try:
                start = datetime.now()
                info = "############ Function name: %s, Text: %s, Starts at: %s ##########" % (
                    func.__name__, text, str(start))
                print info
                func(*args, **kwargs)
                end = datetime.now()
                diff = end - start
                info = "############ Function name: %s, Text: %s, Ends at: %s, cost time: %s ############ " % (
                    func.__name__, text, str(end), str(diff))
                print info
            except Exception as ex:
                info = "Exception type is %s, message is %s" % (ex.__class__.__name__, ex)
                print info
        return wrapper
    return _wrapper


@timeHelperWithParam('run function')
def runWithParam():
    time.sleep(3)

def process():
    run()
    runWithParam()
    newRun = timeHelper(run)
    print newRun.__name__


if __name__ == "__main__":
    process()

猜你喜欢

转载自blog.csdn.net/qingyuanluofeng/article/details/83118933
今日推荐