引言

  以前你有没有这样一段经历:很久之前你写过一个函数,现在你突然有了个想法就是你想看看,以前那个函数在你数据集上的运行时间是多少,这时候你可以修改之前代码为它加上计时的功能,
但是这样的话是不是还要大体读读你之前的这个的代码,稍微搞清楚一点它的逻辑,才敢给它添加新的东西。这样是不是很繁琐,要是你之前写的代码足够乱足够长,再去读它是不是很抓狂...。
实际工作中,我们常常会遇到这样的场景,可能你的需求还不只是这么简单。那么有没有一种可以不对源码做任何修改,并且可以很好的实现你所有需求的手段呢?答案当然是有,这就是今天我
们要介绍的python装饰器。有了装饰器,你除了不用担心前面提到的问题,并且还可以很好的处理接下来要做的事:那就是现在你又有了一个新的需求,比如为另一个函数添加计时功能,这时就
非常简单了,把要装饰的函数丢给装饰器就好了,它会自动给你添加完功能并返回给你。是不是很神奇?下面我们将一层层剥开它的神秘面纱。

 闭包函数

  在看装饰器之前,我们先来搞清楚什么是闭包函数。python是一种面向对象的编程语言,在python中一切皆对象,这样就使得变量所拥有的属性,函数也同样拥有。这样我们就可以理解在函数内创建一个函数的行为是完全合法的。这种函数被叫做内嵌函数,这种函数只可以在外部函数的作用域内被正常调用,在外部函数的作用域之外调用会报错,例如:

       函数 之装饰器

而如果内部函数里引用了外部函数里定义的对象(甚至是外层之外,但不是全局变量),那么此时内部函数就被称为闭包函数。闭包函数所引用的外部定义的变量被叫做自由变量。闭包从语法上看非常简单,但是却有强大的作用。闭包可以将其自己的代码和作用域以及外部函数的作用结合在一起。下面给出一个简单的闭包的例子:

def count():
    a = 1
    b = 1
    def sum():
        c = 1
        return a + c  # a - 自由变量
    return sum

 总结:什么函数可以被称为闭包函数呢?主要是满足两点:函数内部定义的函数;引用了外部变量但非全局变量。

装饰器定义及原则

有了闭包函数的概念,我们再去理解装饰器会相对容易一些。python装饰器本质上就是一个函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外的功能,装饰器的返回值也是一个函数对象(函数的指针)。装饰器函数的外部函数传入我要装饰的函数名字,返回经过修饰后函数的名字;内层函数(闭包)负责修饰被修饰函数。从上面这段描述中我们需要记住装饰器的几点属性,以便后面能更好的理解:

       实质: 是一个函数


    参数:是你要装饰的函数名(并非函数调用)


    返回:是装饰完的函数名(也非函数调用)


    作用:为已经存在的对象添加额外的功能


    特点:不需要对对象做任何的代码上的变动        

定义   

装饰器本质还是一个函数,它是用来对函数函数进行装饰的函数,在不改变原来函数调用的基础上给原来的函数添加新的功能

原则:开放封闭原则

开放:对于原来的函数没有的功能(要添加的新的功能是开放的)
为什么要对扩展开放呢?
    任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改。所以我们必须允许代码扩展、添加新功能。


封闭:对于原来的函数已经实现的功能是封闭的(不能改变原来的函数)

为什么要对修改封闭呢?
    就像我们刚刚提到的,因为我们写的一个函数,很有可能已经交付给其他人使用了,如果这个时候我们对已经写好的函数进行了修改,很有可能影响其他已经在使用该函数的用户。

装饰器完美的遵循了这个开放封闭原则。

装饰器的主要功能及固定框架

装饰器的主要功能

在不改变原函数调用方式的基础上在原函数的前、后添加新的功能

装饰器的固定框架

def timer(func):
    def inner(*args,**kwargs):
        '''执行函数之前要做的'''
        re = func(*args,**kwargs)
        '''执行函数之后要做的'''
        return re
    return inner
装饰器固定形态

相关文章: