python 装饰器最佳实践

www.yunxcloud.cn

首先要明白装饰器是用来给函数增加额外功能的。

常用的工具函数

import time
from functools import wraps
import inspect
import sys
import logging

def timeit(func):
"""统计函数运行时间"""
t0 = time.perf_counter()
func()
return time.perf_counter() - t0

def count(func):
"""统计递归函数执行次数"""
# @wraps(func)
def counted(args):
counted.call_count += 1
return func(
args)
counted.call_count = 0
return counted

def memorize(f):
"""缓存"""
cache = {}
@wraps(f)
def memorized(args):
if args not in cache:
cache[args] = f(
args)
return cache[args]
return memorized

def trace(func):
"""跟踪函数,便于查看过程。"""
def afunc(args):
print("call", func.name, "with", args)
v = func(
args)
print(func.name, "return ",v)
return v
return afunc

def main(fn):
"""@main ---> name == "main" """
if inspect.stack()[1][0].f_locals['name'] == 'main':
args = sys.argv[1:] # Discard the script name from command line
fn(*args) # Call the main function
return fn

带参数的装饰器

def logged(level, name=None, message=None):
def decorate(func):
logname = name if name else func.module
log = logging.getLogger(logname)
@wraps(func)
def wrapper(*args, *kwargs):
logmsg = "{}--call --{}".format(func.name, args)
log.log(level, logmsg)
return func(
args, **kwargs)
return wrapper
return decorate

统计调用次数 增加缓存 增加debug 功能。

@logged(logging.DEBUG)
@count
@memorize
def fib(x):
return x if x < 2 else fib(x-1) + fib(x-2)

print(fib(10), fib.dict)

非常好的实现

flask 和 bottle 中的路由绑定

将add_url_rule 进行了一层包装,能够很简洁的使用装饰器的语法来绑定路由

def route(self, rule, **options):
def decorator(f):
endpoint = options.pop('endpoint', None)
self.add_url_rule(rule, endpoint, f, **options)
return f
return decorator

@route('/')
def example():
pass

flask login 中的判断是否登录了。。

要注意的地方。 装饰器本质上是一个高阶的函数,用来将函数包裹起来。

注意装饰器使用的顺序。

还有就是使用了装饰器的话原函数的一些信息可能会丢掉。需要通过一个方法

来将原函数的一些东西来绑定到新的上面。

博客 https://www.97up.cn/

更多例子

https://wiki.python.org/moin/PythonDecoratorLibrary

你可能感兴趣的:(python 装饰器最佳实践)