装饰器是一种巧妙简洁的魔术,类似于Java中的面向切面编程,我们可以再函数执行前、执行后、抛出异常时做一些工作。利用装饰器,我们可以抽象出一些共同的逻辑,简化代码。而简化代码的同时,就是在增加代码鲁棒性。

一、缓存

# coding:utf8
import time
import json """
简单的内存缓存参数
""" def simple_cache(timeout=3):
def decorator(f):
def ff(*args, **kwargs):
arg = json.dumps([args, kwargs])
res = None
key = f.__module__ + f.__name__ + arg
if hasattr(f, key):
res = getattr(f, key)
if time.time() - res['last_time'] > timeout:
res = None
if res is None:
res = {'last_time': time.time(), 'data': f(*args, **kwargs)}
setattr(f, key, res)
return res['data'] return ff return decorator if __name__ == '__main__':
@simple_cache(timeout=3)
def haha(user_id):
print("haha", user_id) @simple_cache(timeout=3)
def baga(user_id):
print("baga", user_id) haha(0)
baga(0)
haha(0)
haha(1)
time.sleep(5)
haha(1)

二、重试

在进行网络请求时,我们常常需要重试几次才能请求成功。这种套路经常使用,却又嵌套的非常丑陋。此时,我们可以用装饰器将重试逻辑抽象出来。

def retry(count=1):
def dec(f):
def ff(*args, **kwargs):
ex = None
for i in range(count):
try:
ans = f(*args, **kwargs)
return ans
except Exception as e:
ex = e
raise ex return ff return dec db = [] @retry(count=10)
def until_six():
db.append("haha")
print("until_six")
return db[6] print(until_six())

三、兼容旧版参数

库都是随着时间变化而不断丰富的,函数的参数有可能发生变化,使用注解可以简洁完美地兼容旧版本。

lib.py

def add(x, y):
return x + y

haha.py

from lib import add

z = add(x=4, y=5)
print(z)

现在库函数add需要把x变成one,y变成two,同时需要保持haha.py正常运行。

lib.py

change_list = {  # 存放函数名称变化表,统一维护
'add': {
'x': 'one',
'y': 'two',
}
} def legacy(f):
def ff(*args, **kwargs):
if f.__name__ in change_list:
for old_arg, new_arg in change_list[f.__name__].items():
if new_arg not in kwargs and old_arg in kwargs:
kwargs.update({new_arg: kwargs.get(old_arg)})
del kwargs[old_arg]
print(kwargs)
return f(**kwargs) return ff @legacy
def add(one, two, **kwargs):
return one + two

这种方式可以把API的全部变化放到一个统一的配置文件里面,当决定不再支持旧版时,直接从配置文件里面把旧版参数删除掉即可。

四、deprecated

import logging

def deprecated(info):
def decorator(f):
def ff(*args, **kwargs):
logging.warning("%s is deprected. %s" % (f.__name__, info))
res = f(*args, **kwargs)
return res return ff return decorator

Python装饰器几个有用又好玩的例子的更多相关文章

  1. Python装饰器与面向切面编程

    今天来讨论一下装饰器.装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志.性能测试.事务处理等.装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数 ...

  2. python 装饰器、内部函数、闭包简单理解

    python内部函数.闭包共同之处在于都是以函数作为参数传递到函数,不同之处在于返回与调用有所区别. 1.python内部函数 python内部函数示例: def test(*args): def a ...

  3. Python 装饰器(Decorator)

    装饰器的语法为 @dec_name ,置于函数定义之前.如: import atexit @atexit.register def goodbye(): print('Goodbye!') print ...

  4. Python第二十六天 python装饰器

    Python第二十六天 python装饰器 装饰器Python 2.4 开始提供了装饰器( decorator ),装饰器作为修改函数的一种便捷方式,为工程师编写程序提供了便利性和灵活性装饰器本质上就 ...

  5. Python高级特性: 12步轻松搞定Python装饰器

    12步轻松搞定Python装饰器 通过 Python 装饰器实现DRY(不重复代码)原则:  http://python.jobbole.com/84151/   基本上一开始很难搞定python的装 ...

  6. Python 装饰器入门(上)

    翻译前想说的话: 这是一篇介绍python装饰器的文章,对比之前看到的类似介绍装饰器的文章,个人认为无人可出其右,文章由浅到深,由函数介绍到装饰器的高级应用,每个介绍必有例子说明.文章太长,看完原文后 ...

  7. Python装饰器的高级用法(翻译)

    原文地址 https://www.codementor.io/python/tutorial/advanced-use-python-decorators-class-function 介绍 我写这篇 ...

  8. 【低门槛 手把手】python 装饰器(Decorators)原理说明

    本文目的是由浅入深地介绍python装饰器原理 装饰器(Decorators)是 Python 的一个重要部分 其功能是,在不修改原函数(类)定义代码的情况下,增加新的功能 为了理解和实现装饰器,我们 ...

  9. 关于python装饰器

    关于python装饰器,不是系统的介绍,只是说一下某些问题 1 首先了解变量作用于非常重要 2 其次要了解闭包 def logger(func): def inner(*args, **kwargs) ...

随机推荐

  1. C++_友元函数总结(转)

     原文地址:http://blog.csdn.net/insistgogo/article/details/6608672   1.为什么要引入友元函数:在实现类之间数据共享时,减少系统开销,提高效率 ...

  2. 【大数据】大数据处理-Lambda架构-Kappa架构

    大数据处理-Lambda架构-Kappa架构 elasticsearch-head Elasticsearch-sql client NLPchina/elasticsearch-sql: Use S ...

  3. NLP常用信息资源

    ACL Anthology,囊括了ACL,EMNLP,CL等NLP领域重要会议和期刊的论文.http://www.aclweb.org/anthology-new/ LDC: The Linguist ...

  4. List 集合的交集

    private void Test() { List<string> lsA = new List<string>(); lsA.Add("A"); lsA ...

  5. 转: linux进程地址图解

    http://www.cnblogs.com/clover-toeic/p/3754433.html

  6. (转)Unity3d中的碰撞检测

    很多时候,当我们的主角与其他GameObject发生碰撞时, 我们需要做一些特殊的事情,比如:子弹击中敌人,敌人就得执行一系列的动作.这时,我们就需要检测到碰撞现象,即碰撞检测.这一篇,我来具体谈谈自 ...

  7. c++ string wstring 字符串替换

      int CStringTool::Replace(std::wstring& strContent, std::wstring& strReplace, std::wstring  ...

  8. javascript获取时间差

    function GetDateDiff(startTime, endTime, diffType) { //将xxxx-xx-xx的时间格式,转换为 xxxx/xx/xx的格式 startTime ...

  9. spring结合mybatis实现数据库读写分离

    随着系统用户访问量的不断增加,数据库的频繁访问将成为我们系统的一大瓶颈之一.由于项目前期用户量不大,我们实现单一的数据库就能完成.但是后期单一的数据库根本无法支撑庞大的项目去访问数据库,那么如何解决这 ...

  10. phpMyadmin安装极简教程[下载,解压,登录]

    1.下载一个压缩包,例如: 2. 解压到web根目录并重命名为phpmyadmin 3.在浏览器输入http://localhost/phpmyadmin就可以看到登陆界面了,登陆之后,数据库,表的增 ...