来源:python中国网 时间:2020-05-18

  python装饰器并不是什么神奇之物,更像是python作者的"装逼"之物,python装饰器实际上是python作者对函数做了一层封装,让一个函数在执行前先发生点别的事!某些场景会让我们写代码的人用起来更加简洁。

  为了了解装饰器,我们从一个现实的场景中来感受:技术部需要给运营部seo优化师和sem优化师提供数据查询服务,这个服务很简单,一直以来都是如下操作。

# -*- coding: utf-8 -*-


def seo():
    print('获取seo数据')


def sem():
    print('获取sem数据')


  现在要做安全升级,凡是查询数据的人都要进行验证,于是技术小哥就本能的写了个验证函数,然后再原有的查询函数中增加了该函数

# -*- coding: utf-8 -*-


def check_person():
    """
    一段操作
    """
    print('验证ok')

def seo():
    check_person()
    print('获取seo数据')
    
def sem():
    check_person()
    print('获取sem数据')


  技术总监一看发现这厮把原来的函数塞了一堆自己的代码进去就很不满意,让他再改善改善。小哥灵机一动又变了变写法,干脆自己定义新的函数。

# -*- coding: utf-8 -*-


def check_person():
    """
    一段操作
    """
    print('验证ok')


def new_seo():
    check_person()
    print('获取seo数据')
new_seo()



def new_sem():
    check_person()
    print('获取sem数据')
new_sem()


  技术总监看了后还不满意,他说写代码要遵循开放封闭原则,已经实现的功能代码不允许被修改。让技术小哥思考如何不改变原来的函数且调用原函数还能实现新加的功能,小哥突然脑洞一开就把代码进行了改造。

# -*- coding: utf-8 -*-


# 参数是函数名
def new_check(func):
    def check_person():
        """
        一顿验证操作
        """
        print('验证ok')
        func()
    return check_person


# 把原来的函数名当做参数传递,把返回的函数仍然命名为原始的函数名
seo = new_check(seo)
seo()
sem = new_check(sem)
sem()


  经过这么巧妙的改造确实遵循了开放封闭的原则,但是总感觉有点啰嗦,别担心。这一切其实都在python作者预料之中,python给你提供了装饰器来实现,只需要一个@符号来实现。

# -*- coding: utf-8 -*-


def new_check(func):
    def check_person():
        """
        一顿验证操作
        """
        print('验证ok')
        func()
    return check_person


@new_check
def seo():
    print('seo要查询数据了')
seo()


@new_check
def sem():
    print('sem要查询数据了')
sem()
验证ok
seo要查询数据了
验证ok
sem要查询数据了


上面就是装饰器的原理,就用了一下闭包的知识,没有什么复杂之处。只是python作者给提供了一个@符号来掩盖了中间的过程,所以让人感觉很高端,这叫python语法糖!

先了解基本原理,含有参数的函数被装饰、多个装饰器同时装饰一个函数的情况,我们后面再讲。