Python 装饰器总结

装饰器总结

前提

使用装饰器的前提在于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. 在装饰器的基础上还可以进行装饰,比如装饰装饰器的装饰器。

最后写一个题目,写一个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

时间: 2024-12-13 19:01:32

Python 装饰器总结的相关文章

5.初识python装饰器 高阶函数+闭包+函数嵌套=装饰器

一.什么是装饰器? 实际上装饰器就是个函数,这个函数可以为其他函数提供附加的功能. 装饰器在给其他函数添加功能时,不会修改原函数的源代码,不会修改原函数的调用方式. 高阶函数+函数嵌套+闭包 = 装饰器 1.1什么是高阶函数? 1.1.1函数接收的参数,包涵一个函数名. 1.1.2 函数的返回值是一个函数名. 其实这两个条件都很好满足,下面就是一个高阶函数的例子. def test1(): print "hamasaki ayumi" def test2(func): return t

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

python装饰器 刚刚接触python的装饰器,简直懵逼了,直接不懂什么意思啊有木有,自己都忘了走了多少遍Debug,查了多少遍资料,猜有点点开始明白了.总结了一下解释得比较好的,通俗易懂的来说明一下: 小P闲来无事,随便翻看自己以前写的一些函数,忽然对一个最最最基础的函数起了兴趣: 1 def sum1(): 2 sum = 1 + 2 3 print(sum) 4 sum1() 此时小P想看看这个函数执行用了多长时间,所以写了几句代码插进去了: 1 import time 2 3 def

python装饰器1

第八步:让装饰器带 类 参数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 # -*- coding:gbk -*- '''示例8: 装饰器带类参数''' class locker:     def __init__(self):         print("locker.__init__() should be not called.")   

Python装饰器由浅入深

装饰器的功能在很多语言中都有,名字也不尽相同,其实它体现的是一种设计模式,强调的是开放封闭原则,更多的用于后期功能升级而不是编写新的代码.装饰器不光能装饰函数,也能装饰其他的对象,比如类,但通常,我们以装饰函数为例子介绍其用法.要理解在Python中装饰器的原理,需要一步一步来.本文尽量描述得浅显易懂,从最基础的内容讲起. (注:以下使用Python3.5.1环境) 一.Python的函数相关基础 第一,必须强调的是python是从上往下顺序执行的,而且碰到函数的定义代码块是不会立即执行它的,只

python 装饰器学习(decorator)

最近看到有个装饰器的例子,没看懂, #!/usr/bin/python class decorator(object): def __init__(self,f): print "initial decorator" f() def __call__(self): print "call decorator" @decorator def fun(): print "in the fun" print "after " fun

【转】九步学习python装饰器

本篇日志来自:http://www.cnblogs.com/rhcad/archive/2011/12/21/2295507.html 纯转,只字未改.只是为了学习一下装饰器.其实现在也是没有太看明白,对于装饰器我就是用的时候找例子,能蒙对,但是用过之后一段时间就忘了.还是用的少.有空应该好好看一看的,包括闭包.对于各种现代编程语言来说闭包都是很重要的.在这里先谢过原作者,如有侵权请告知. =-=-=-=-=-=-=-=-=-=-一条不怎么华丽的分隔线-=-=-=-=-=-=-=-=-=-= 这

【Python之旅】第四篇(一):Python装饰器

有时候拿到一个程序接口,需要对其进行扩展,但是又不能修改原来接口的源代码,这时候就需要使用装饰器了. 有下面一个小程序,假如是别人提供给我们的调用接口: import time def sayHi():         time.sleep(1)         print 'Hello, I am xpleaf.' 一般情况下,如果想要计算该程序的执行时间(因为有可能要对该接口进行某些性能上的测试),就需要把以上接口修改为下面这样,同时执行一下: 程序代码: import time def s

python装饰器原理及相关操作

python装饰器,简单的说就是用于操作底层代码的代码,在不改变底层代码函数的情况下对底层代码进行验证操作等 首先,必须知,道调用func和func的区别,分别为返回函数所在的内存地址和调用该函数,输出执行结果,例如: def func(): print("欢迎光临!!!") print("返回函数所在的内存地址:",func) func() 列举一个简单的web页面调用例子 1 #做登录验证 2 def login(func): 3 print("登录成

python装饰器学习笔记

什么是python装饰器? 装饰器其实也就是一个函数,一个用来包装函数的函数,返回一个修改之后的函数对象,将其重新赋值原来的标识符,并永久丧失对原始函数对象的访问. eg:当需要在Func1和Func2中加一样的功能时,可以在outer中添加一次就可以完成全部函数的添加.装饰器与函数建立连接的方式是在函数的前一行用@+装饰器名称来完成.并且在装饰器中一定要返回被装饰的对象 def outer(fun):     def wrapper():         print '验证'         

python 装饰器及标准库functools中的wraps

最近在看 flask的视图装饰器 时,忽然想起预(复)习一下python的装饰器. 这里有一篇比较好的讲解装饰器的书写的 Python装饰器学习(九步入门) . 这里不单独记录装饰器的书写格式了,重点是工作流程. 首先常见的 装饰器 格式就是通过@语法糖,简便的写法,让流程有些不太清楚. 装饰器不带参数的情况下: def deco(func):     def _deco():         print("before myfunc() called.")         func(