orangle / blog

博客--自我学习监督
http://orangleliu.info
3 stars 0 forks source link

Python 常用装饰器 #10

Open orangle opened 7 years ago

orangle commented 7 years ago

运行时间统计,统计项相对简单

def timefn(fn):
    @wraps(fn)
    def count_time(*args, **kwargs):
        st = time.time()
        res = fn(*args, **kwargs)
        ed = time.time()
        print "@time: {0} tasks {1} secs".format(fn.func_name, str(ed-st))
        return res
    return count_time

错误重试或者是超时重试类似的

import time
from functools import wraps

def retry(ExceptionToCheck, tries=4, delay=3, backoff=2, logger=None):
    def deco_retry(f):
        @wraps(f)
        def f_retry(*args, **kwargs):
            mtries, mdelay = tries, delay
            while mtries > 1:
                try:
                    return f(*args, **kwargs)
                except ExceptionToCheck, e:
                    msg = "%s, Retrying in %d seconds..." % (str(e), mdelay)
                    if logger:
                        logger.warning(msg)
                    else:
                        print msg
                    time.sleep(mdelay)
                    mtries -= 1
                    mdelay *= backoff
            return f(*args, **kwargs)
        return f_retry  # true decorator
    return deco_retry

装饰器带有默认参数

http://blog.dhananjaynene.com/2013/10/partially-applied-functions-and-decorators-in-python/

from functools import wraps

def trace(trace_arguments = False) :
    def decorator(func) :
        @wraps(func)
        def wrapper(*args, **kwargs) :
            if trace_arguments :
                print("Entering {} with arguments {} {}".format(
                                                func.__name__, args, kwargs))
            else :
                print("Entering {}".format(func.__name__))
            ret = func(*args, **kwargs)
            if trace_arguments :
                print("Leaving {} with result {}".format(func.__name__, ret))
            else :
                print("Leaving {}".format(func.__name__))
            return ret
        return wrapper
    return decorator

# using a global for brevity

function_calls = 0
def track(func) :
    @wraps(func)
    def wrapper(*args, **kwargs):
        global function_calls
        function_calls = function_calls + 1
        return func(*args, **kwargs)
    return wrapper

@track
@trace(True)
def add(a, b) :
    return a + b

print("Function calls so far {}".format(function_calls))
print("3 + 5 = {}".format(add(3,5)))
print("2 + 7 = {}".format(add(2,7)))
print("Function calls so far {}".format(function_calls))

另一个种方式

from functools import partial

def _pseudo_decor(fun, argument):
    def ret_fun(*args, **kwargs):
        #do stuff here, for eg.
        print "decorator arg is %s" % str(argument)
        return fun(*args, **kwargs)
    return ret_fun

real_decorator = partial(_pseudo_decor, argument=arg)

@real_decorator
def foo(*args, **kwargs):
    pass

装饰器自动注入参数,类似django views中的自动注入request

# 通过参数传参数,也可以通过修改 function 的参数字典
def decorate(function):
    def wrap_function(*args, **kwargs):
        kwargs['str'] = 'Hello!'
        return function(*args, **kwargs)
    return wrap_function

@decorate
def print_message(*args, **kwargs):
    print(kwargs['str'])

# 通过修改function的参数列表
def decorate(function):
    def wrap_function(*args, **kwargs):
        str = 'Hello!'
        return function(str, *args, **kwargs)
    return wrap_function

@decorate
def print_message(str, *args, **kwargs):
    print(str)

# 给类添加
def decorate(function):
    def wrap_function(*args, **kwargs):
        str = 'Hello!'
        args.insert(1, str)
        return function(*args, **kwargs)
    return wrap_function

class Printer:
    @decorate
    def print_message(self, str, *args, **kwargs):
        print(str)
zhangdavids commented 4 years ago

很赞 :clap: