Python装饰器详解

@author StormMa
@date 2017-06-09


生命不息,奋斗不止!


开始之前

第一次接触Python的时候就是直接开始写一些爬虫或者是使用django写简单的web应用,但是最近想回头来看看Python中好玩的特性或者是基础。今天就来看一下装饰器的使用,其实感觉Python中的装饰器,有点类似于Java中的Aspect。就像你在一个方法中处理主要的业务逻辑,如果要想在处理业务逻辑之前打印一下日志的话,那么可以使用装饰器来装饰一下原函数,在此要说明一下,这里的装饰器和Java中的装饰器模式原理上还是相通的,但是Java中的装饰器模式是对对象的增强,如果使用Java装饰器模式实现,调用也要修改,但是Python中的这种实现之前的调用方式就不用做修改。

小例子

首先,我们用一个简单的示例来展示一下装饰器的真实面貌,就用我们之前说的增加一个打印日志的功能来装饰一个函数吧,我相信这个例子你一定可以看懂。

def log(func):
    def wrapper(*args, **kwargs):
        print("执行%s之前" % (func.__name__))
        func()
        print("执行%s之后" % (func.__name__))
    return wrapper
@log
def handle():
    print("处理主要的业务逻辑")

if __name__ == '__main__':
    handle()

上面的执行接口就是在打印handle里面的内容之前和之后分别打印了log中的日志内容。是不是就像是Java中Aspect的实现结果。我们来分析一下这个代码吧,这个代码比普通的函数调用就多了一个@log的annotation,其实@log翻译过来就是 handle = log(handle), 所以此时handle这个变量指向的不是原来的handle指向的函数,而是log返回的wrapper函数,我们原来的函数handle已经赋值给func这个变量了,此时的指向是这样的: handle –> wrapper, func –> 原来的handle指向的函数。那么此时调用handle,就是执行wrapper函数,wrapper函数中执行func就是原来的handler函数,这样就达到增强函数的效果了,其实也就是装饰器(这个名字叫的真不错,嘿哈)!其实注解这个语法就是把一个函数当做参数传递,然后回调函数的一个套路。

带参数的装饰器

如果我要在打印之前传递一个参数怎么办呢?

import time


def log(time):
    def decorator(func):
        def wrapper(*args, **kwargs):
            print(time.title())
            print("执行%s之前" % (func.__name__))
            func()
            print("执行%s之后" % (func.__name__))
        return wrapper
    return decorator
@log(time=time.ctime())
def handle():
    print("处理主要的业务逻辑")

if __name__ == '__main__':
    handle()

读者可以根据我前面对那个小例子的分析来分析这段代码。假设你心里面已经有数了。只要我们知道@log(time=xxxx)这个东西到底怎么解释就解决了所有的疑惑。这次的@log(time=xxxx)解释成 handle = log(time=xxxx)(handle),handle指向的还是wrapper最后回调的还是func指向的原来的handle指向的函数,我觉得我们理解成log(time=xxxx)返回的是decorator,然后@log(time=xxxx)等价于@ decorator这个了,然后剩下就和上面那个例子一样了,如果对变量指向函数疑惑的同学,可以打印一下这两个例子中handle的name的属性,你会发现它们的结果是一样的都是wrapper,所以结果就是

Fri Jun  9 09:43:41 2017
执行handle之前
处理主要的业务逻辑
执行handle之后

本文来自我的个人站点: http://blog.stormma.me,转载请注明出处!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值