Python 装饰器总结
装饰器总结
前提
使用装饰器的前提在于Python提供的特性:
- 函数即对象,可以进行传递;
- 函数可以被定义在另外一个函数中;
可以通过一个例子来了解:
def get_animal(name='dog'):
def dog():
return 'this is a dog'
def cat():
return 'this is a cat'
# 返回函数对象
if name == 'dog':
return dog
elif name == 'cat':
return cat
else:
return 'other animal'
animal = get_animal('cat')
print(animal) # <function get_animal.<locals>.cat at 0x104b30d90>
print(animal())
注意:其返回的并不是调用函数,而是返回函数对象,只有在函数对象后面加上括号才表明要进行调用对象。
装饰器
装饰器就是可以在原来函数的基础上增加其它的功能,而不改变原函数本身。
如何写一个装饰器呢,下面给出一个基础的模版:
def my_decorator(a_function_to_decorate):
def wapper_function(*args, **kwargs):
print('Before the function runs')
a_function_to_decorate(*args, **kwargs)
print('After the function runs')
return wapper_function
@my_decorator
def stand_function():
print('stand function runs')
stand_function()
执行结果为:
Before the function runsstand function runsAfter the function runs
如果要求原函数的信息不变,那么可以使用functools.wraps
,其本身也是一个装饰器,作用是将原函数的名称、模块、文档字符串等拷贝到装饰器里面的fun函数中,例子如下:
# "functools" 可以改变这点
import functools
def bar(func):
@functools.wraps(func)
def wrapper():
return func()
return wrapper
需要注意的问题是:
- 如果有多个装饰器的时候,则由里到外装饰,也就是按照距离函数的位置谁越近越就被装饰。
- 在装饰器的基础上还可以进行装饰,比如装饰装饰器的装饰器。
如果我们想要使用类来作为装饰器,那么被装饰的函数会作为类的参数被传入到类中。
比如写一个登陆检查的例子:
class LoginCheck:
def __init__(self, f):
self._f = f
def __call__(self, *args):
Status = check_function()
if Status is True:
return self._f(*args)
else:
return alt_function()
def check_function():
return True
def alt_function():
return('Sorry - this is the forced behaviour')
@LoginCheck
def display_members_page():
print('This is the members page')
display_members_page()
过程:它在访问相应的页面的时候,会进行登陆与否的检查,成功则返回相应的信息,反之则提示。
最后写一个题目,写一个decorator,在函数开始和结束时增加log,并且统计函数执行时间,保留原函数名:
import logging, time
def create_logger():
logger = logging.getLogger("example_logger")
logger.setLevel(logging.INFO)
# create the logging file handler
handler = logging.FileHandler(r"./test.log")
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
# add handler to logger object
logger.addHandler(handler)
return logger
def exception(logger):
def decorator(func):
def wrapper(*args, **kwargs):
start = time.time()
try:
logger.info('function runs')
res = func(*args, **kwargs)
print('the function used time: {}'.format(time.time()-start))
logger.info('function stops')
return res
except:
# log the exception
err = "There was an exception in "
err += func.__name__
logger.exception(err)
raise Exception
return wrapper
return decorator
logger = create_logger()
@exception(logger=logger)
def foo(name='foo_function'):
print('i am {}'.format(name))
return True
print(foo())
运行结果如下:
i am foo_functionthe function used time: 0.0008778572082519531True
logger中的结果如下:
2017-08-15 03:25:59,234 - example_logger - INFO - function runs2017-08-15 03:25:59,235 - example_logger - INFO - function stops
Python 装饰器总结的更多相关文章
- 关于python装饰器
关于python装饰器,不是系统的介绍,只是说一下某些问题 1 首先了解变量作用于非常重要 2 其次要了解闭包 def logger(func): def inner(*args, **kwargs) ...
- python装饰器通俗易懂的解释!
1.python装饰器 刚刚接触python的装饰器,简直懵逼了,直接不懂什么意思啊有木有,自己都忘了走了多少遍Debug,查了多少遍资料,猜有点点开始明白了.总结了一下解释得比较好的,通俗易懂的来说 ...
- Python 装饰器学习
Python装饰器学习(九步入门) 这是在Python学习小组上介绍的内容,现学现卖.多练习是好的学习方式. 第一步:最简单的函数,准备附加额外功能 1 2 3 4 5 6 7 8 # -*- c ...
- python 装饰器修改调整函数参数
简单记录一下利用python装饰器来调整函数的方法.现在有个需求:参数line范围为1-16,要求把9-16的范围转化为1-8,即9对应1,10对应2,...,16对应8. 下面是例子: def fo ...
- python 装饰器学习(decorator)
最近看到有个装饰器的例子,没看懂, #!/usr/bin/python class decorator(object): def __init__(self,f): print "initi ...
- Python装饰器详解
python中的装饰器是一个用得非常多的东西,我们可以把一些特定的方法.通用的方法写成一个个装饰器,这就为调用这些方法提供一个非常大的便利,如此提高我们代码的可读性以及简洁性,以及可扩展性. 在学习p ...
- 关于python装饰器(Decorators)最底层理解的一句话
一个decorator只是一个带有一个函数作为参数并返回一个替换函数的闭包. http://www.xxx.com/html/2016/pythonhexinbiancheng_0718/1044.h ...
- Python装饰器由浅入深
装饰器的功能在很多语言中都有,名字也不尽相同,其实它体现的是一种设计模式,强调的是开放封闭原则,更多的用于后期功能升级而不是编写新的代码.装饰器不光能装饰函数,也能装饰其他的对象,比如类,但通常,我们 ...
- Python装饰器与面向切面编程
今天来讨论一下装饰器.装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志.性能测试.事务处理等.装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数 ...
- python装饰器方法
前几天向几位新同事介绍项目,被问起了@login_required的实现,我说这是django框架提供的装饰器方法,验证用户是否登录,只要这样用就行了,因为自己不熟,并没有做过多解释. 今天查看dja ...
随机推荐
- C#深入学习 ----多线程学习(一)第一天学习
学习最好的方法就是总结,并写下来,能让别人看懂,自己肯定是掌握了的. 针对软件开发,一直停留在能做的层次,今天得到大牛指点,觉得有必要对这门技术深入学习. 翻阅园内各大神的文章,收益匪浅,在这里做下总 ...
- 关于在eclipse上部署Tomcat时出现8080等端口被占用问题的解决方法
问题描述: 在eclipse中部署Tomcat时,出现如下错误. 解决方法如下: 方法一: 1.开始->cmd->输入命令netstat -ano出现下图所示(注意下边显示有些错位,最后一 ...
- editPuls 常用知识
1.创建模板 1).创建模板页(*.html) 2).Tools->Preferences->File->Templates->HTML->file name重新选定模板 ...
- Echarts报错[MODULE_MISS]"echarts/config" is not exists!
项目用到Echarts插件,时下比较流行的是模块化包引入,但是很悲催的是楼主用的是标签式引入,所以从官网copy来的代码总是报一个 [MODULE_MISS]"echarts/config的 ...
- tcp入门(唐唐的故事)
1,互联网的实现,分成好几层.每一层都有自己的功能,就像建筑物一样,每一层都靠下一层支持.把互联网分成五层,容易让人理解. 2,对这五层的理解(唐唐讲故事): 实体层:目的就是把计算机连接起来,用电气 ...
- ubuntu14.04_CUDA8.0_cudnn5.1_Tensorflow配置
深度学习框架tensorflow相比与caffe抽象层做的更好,即使用tensorflow的人不需要关心底层的实现,做底层实现的人不需要关心上层的模型和算法;caffe耦合比较紧凑,若想caffe用的 ...
- “玲珑杯”ACM比赛 Round #12 (D) 【矩阵快速幂的时间优化】
//首先,感谢Q巨 题目链接 定义状态向量b[6] b[0]:三面临红色的蓝色三角形个数 b[1]:两面临红色且一面临空的蓝色三角形个数 b[2]:一面临红色且两面临空的蓝色三角形个数 b[3]:三面 ...
- (转)使用BigDecimal进行精确运算
场景:在进行支付业务的金额计算时,通常采用BigDecimal类型的数据,并没有看到常见的int double类型,所以有必要好好学习下BigDecimal的常用用法. 1 误区 首先我们先来看如下代 ...
- 史上最易懂——ReactNative分组列表SectionList使用详情及示例详解
React Native系列 <逻辑性最强的React Native环境搭建与调试> <ReactNative开发工具有这一篇足矣> <解决React Native un ...
- 解决div里面img的缝隙问题(转)
图片IMG与容器下边界之间有空隙怎么办?这里介绍3中简单的解决方法. 第一,给图片img标签display:block. img{display:block} 第二,定义容器里的字体大小为0. div ...