博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python_装饰器
阅读量:3972 次
发布时间:2019-05-24

本文共 3200 字,大约阅读时间需要 10 分钟。

装饰器是python基础语法中比较晦涩难懂的地方,借此机会,谈谈自己对装饰器的理解。

文章目录

一、什么是装饰器

装饰:给别的函数添加功能

器:就是具有某种作用的工具

装饰器:给其他函数添加功能的工具,本质也是函数,而且是一个闭包函数。

二、为什么要有装饰器

一、函数传参的另外一种形式

之前我们学的函数传参都是类似于如下:

def func(a,b):    print(a,b)

有了装饰器之后我们可以这样传参:

这里是为deco传的参数,这里的deco就是一个装饰器,他需要一个参数是func,即被装饰函数的地址

def wrapper(func):    def deco(*args,**kwargs):        print('in the wrapper')        res = func(*args,**kwargs)        return res     return decodef func2():    print(123)

那为什么不这样写?

def deco(func,*args,**kwargs):        print('in the wrapper')        res = func(*args,**kwargs)        return res

我将在下面解释

二、在不改变函数源代码和调用方式的情况下为函数添加功能,具体用法在下面介绍

三、怎么用装饰器

def wrapper(func):    def deco(*args,**kwargs):        print('in the wrapper')        res = func(*args,**kwargs)        return res     return decodef func2():    print(123)

前面已经说过,deco就是一个装饰器,本质是闭包函数。对于闭包函数简单一提,在python中万物皆对象,因此函数也可以作为其他函数的参数、返回值、也可以作为容器类型的元素

x = 4def deco():	x = 1    def func():        print(x)

闭:可以理解为一个麻袋把函数套起来,这里的麻袋就是deco

包:可以理解为麻袋里面的东西,这里的x就是麻袋里的东西,这里打印的x是1

闭包函数的名字的查找关系是以函数定义阶段为准,可以理解为局部变量覆盖了全局变量

四、语法糖

形式:@函数名

def wrapper(func):    def deco(*args,**kwargs):        print('in the wrapper')        res = func(*args,**kwargs)        return res     return deco@wrapperdef func2():    print(123)

这里func2被deco装饰,@wrapper等价于func2 = wrapper(func2),为func2多加了一个功能,即打印了in the wrapper,那为什么不能在定义deco的时候多一个函数参数呢,那是因为实际上func2变成了 deco,真正调用func2的时候会是这样

func2()

func2被装饰后,运行的就是deco了,但是用户丝毫不清楚这个过程,因为调用方式没变,函数(指的是func2)的代码也没变,如果加上一个函数参数,那么在调用的时候会出错,说是少了一个参数。这里的deco参数和func2的函数应该保持一致。

有参装饰器,简单一提(其实可以不用语法糖实现,省略,因为比较low)

def outter(x):    def wrapper(func):        print(x)        def deco(*args,**kwargs):            print('in the wrapper')            res = func(*args,**kwargs)            return res        return deco    return wrapper@outter(1)def func2():    print(123)func2()

多层装饰器的加载顺序是从下往上,运行顺序是从上往下。

def deco1(func1): # func1 = wrapper2的内存地址    def wrapper1(*args,**kwargs):        print('正在运行===>deco1.wrapper1')        res1=func1(*args,**kwargs)        return res1    return wrapper1def deco2(func2): # func2 = wrapper3的内存地址    def wrapper2(*args,**kwargs):        print('正在运行===>deco2.wrapper2')        res2=func2(*args,**kwargs)        return res2    return wrapper2def deco3(x):    def outter3(func3): # func3=被装饰对象index函数的内存地址        def wrapper3(*args,**kwargs):            print('正在运行===>deco3.outter3.wrapper3')            res3=func3(*args,**kwargs)            return res3        return wrapper3    return outter3# 加载顺序自下而上(了解)@deco1      # index=deco1(wrapper2的内存地址)        ===> index=wrapper1的内存地址@deco2      # index=deco2(wrapper3的内存地址)        ===> index=wrapper2的内存地址@deco3(111) # ===>@outter3===> index=outter3(index) ===> index=wrapper3的内存地址def index(x,y):    print('from index %s:%s' %(x,y))# 执行顺序自上而下的,即wraper1-》wrapper2-》wrapper3index(1,2) # wrapper1(1,2)

更加伪装:

from functools import wrapsdef outter(func):    @wraps(func)    def wrapper(*args, **kwargs):        """这个是主页功能"""        res = func(*args, **kwargs) # res=index(1,2)        return res    # 手动将原函数的属性赋值给wrapper函数    # 1、函数wrapper.__name__ = 原函数.__name__    # 2、函数wrapper.__doc__ = 原函数.__doc__    # wrapper.__name__ = func.__name__    # wrapper.__doc__ = func.__doc__    return wrapper

讲解链接:

python

转载地址:http://ifxki.baihongyu.com/

你可能感兴趣的文章
UTF-16 编码简介
查看>>
Java 变量名
查看>>
Java 四舍五入运算
查看>>
Spring Batch 例子: 运行系统命令
查看>>
Spring Batch 核心概念
查看>>
Spring Batch 例子: 导入定长文件到数据库
查看>>
正则表达式
查看>>
Java I/O
查看>>
序列化
查看>>
Perl 精萃
查看>>
Perl 简介
查看>>
Perl 注释
查看>>
数据类型之标量
查看>>
增强的for循环语句
查看>>
数据类型之列表与数组
查看>>
Open Source 精萃
查看>>
Java EE 简介
查看>>
Weblogic 简介
查看>>
观察者模式 (Observer)
查看>>
Java 集合框架
查看>>