Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python 常用装饰器 #10

Open
orangle opened this issue Dec 8, 2016 · 1 comment
Open

Python 常用装饰器 #10

orangle opened this issue Dec 8, 2016 · 1 comment
Labels

Comments

@orangle
Copy link
Owner

orangle commented Dec 8, 2016

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

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)
@orangle orangle added the 积累 label Dec 8, 2016
@zhangdavids
Copy link

很赞 👏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants