装饰器总结

前提

使用装饰器的前提在于Python提供的特性:

  1. 函数即对象,可以进行传递;
  2. 函数可以被定义在另外一个函数中;

可以通过一个例子来了解:

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

需要注意的问题是:

  1. 如果有多个装饰器的时候,则由里到外装饰,也就是按照距离函数的位置谁越近越就被装饰。
  2. 在装饰器的基础上还可以进行装饰,比如装饰装饰器的装饰器。

如果我们想要使用类来作为装饰器,那么被装饰的函数会作为类的参数被传入到类中。

比如写一个登陆检查的例子:

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 装饰器总结的更多相关文章

  1. 关于python装饰器

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

  2. python装饰器通俗易懂的解释!

    1.python装饰器 刚刚接触python的装饰器,简直懵逼了,直接不懂什么意思啊有木有,自己都忘了走了多少遍Debug,查了多少遍资料,猜有点点开始明白了.总结了一下解释得比较好的,通俗易懂的来说 ...

  3. Python 装饰器学习

    Python装饰器学习(九步入门)   这是在Python学习小组上介绍的内容,现学现卖.多练习是好的学习方式. 第一步:最简单的函数,准备附加额外功能 1 2 3 4 5 6 7 8 # -*- c ...

  4. python 装饰器修改调整函数参数

    简单记录一下利用python装饰器来调整函数的方法.现在有个需求:参数line范围为1-16,要求把9-16的范围转化为1-8,即9对应1,10对应2,...,16对应8. 下面是例子: def fo ...

  5. python 装饰器学习(decorator)

    最近看到有个装饰器的例子,没看懂, #!/usr/bin/python class decorator(object): def __init__(self,f): print "initi ...

  6. Python装饰器详解

    python中的装饰器是一个用得非常多的东西,我们可以把一些特定的方法.通用的方法写成一个个装饰器,这就为调用这些方法提供一个非常大的便利,如此提高我们代码的可读性以及简洁性,以及可扩展性. 在学习p ...

  7. 关于python装饰器(Decorators)最底层理解的一句话

    一个decorator只是一个带有一个函数作为参数并返回一个替换函数的闭包. http://www.xxx.com/html/2016/pythonhexinbiancheng_0718/1044.h ...

  8. Python装饰器由浅入深

    装饰器的功能在很多语言中都有,名字也不尽相同,其实它体现的是一种设计模式,强调的是开放封闭原则,更多的用于后期功能升级而不是编写新的代码.装饰器不光能装饰函数,也能装饰其他的对象,比如类,但通常,我们 ...

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

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

  10. python装饰器方法

    前几天向几位新同事介绍项目,被问起了@login_required的实现,我说这是django框架提供的装饰器方法,验证用户是否登录,只要这样用就行了,因为自己不熟,并没有做过多解释. 今天查看dja ...

随机推荐

  1. Http批量异步发送和数据保存

    先说需求. 有个服务程序定时扫描指定文件夹下一个所有文件,文件包含了多个用户(客户)信息及对应的http发送地址和发送数据.现在该服务程序需要提取这些用户信息,然后批量进行发送:发送完后需要将http ...

  2. chart.js使用常见问题

    Chart.js是一个简单.面向对象.为设计者和开发者准备的图表绘制工具库. 在使用过程中新手可能会遇到很多问题导致图标无法显示.下面我们来看一下在使用过程中可能会遇到的问题. 刚开始用chart.j ...

  3. 使用 sitemesh/decorator装饰器装饰jsp页面(原理及详细配置)

    摘要:首先这个Decorator解释一下这个单词:“装饰器”,我觉得其实可以这样理解,他就像我们用到的Frame,他把每个页面共有的东西提炼了出来,也可能我们也会用各种各样的include标签,将我们 ...

  4. 在ASP.NET Core配置环境变量和启动设置

    在这一部分内容中,我们来讨论ASP.NET Core中的一个新功能:环境变量和启动设置,它将开发过程中的调试和测试变的更加简单.我们只需要简单的修改配置文件,就可以实现开发.预演.生产环境的切换. A ...

  5. JavaScript从入门到忘记

    JavaScript是一门编程语言,浏览器内置了JavaScript语言的解释器,所以在浏览器上按照JavaScript语言的规则编写相应代码之,浏览器可以解释并做出相应的处理. 一.如何编写 二.变 ...

  6. Oracle11g 创建表空间、创建用户、角色授权、导入导出表以及中文字符乱码问题

    前提:本机已经安装了Oracle11g数据库. 需求:使用PL SQL数据库连接工具操作Oracle数据库 一.创建表空间和用户      想要操作数据库,首先需要创建用户并给用户授予权限:在创建用户 ...

  7. Spring实现IoC的多种方式

    目录 一.使用XML配置的方式实现IOC 二.使用Spring注解配置IOC 三.自动装配 四.零配置实现IOC 五.示例下载 控制反转IoC(Inversion of Control),是一种设计思 ...

  8. JavaScript+canvas 绘制多边形

    效果图: <body> <canvas id="square" width="500"></canvas> <canv ...

  9. 一个Web 持续集成工作实践

    一个web的持续基础实践: https://mp.weixin.qq.com/src=3&timestamp=1494325174&ver=1&signature=wFVC0E ...

  10. Java中的数值和集合

    数组array和集合的区别: (1) 数值是大小固定的,同一数组只能存放一样的数据. (2) java集合可以存放不固定的一组数据 (3) 若程序事不知道究竟需要多少对象,需要在空间不足时自动扩增容量 ...