python3之路 基础-装饰器

本文介绍了Python3中的装饰器,这是一种在不修改源代码和调用方式的情况下为函数添加额外功能的技术。装饰器基于函数即“变量”的概念,结合高阶函数和嵌套函数实现。文章通过逐步解析和示例,阐述了装饰器的工作原理,包括如何避免改变被装饰函数的源代码和调用方式,以及如何使用@语法糖简化调用过程。
摘要由CSDN通过智能技术生成
疑问

有没有一种方式,在不改变代源码、不改变调用方式的情况下,对函数增加功能。添加一些我们需要的方法、逻辑。

这时候装饰器就出现了。装饰器,看其名知其意。在不改变原有结构的情况下,让其本身具有之前不具有的功能。

实现装饰器的知识储备:

  1. 函数即“变量”
  2. 高阶函数
    把一个函数名当做实参传递给另外一个函数
    返回值中包含函数名
  3. 嵌套函数
    在函数体内,使用def再声明一个函数。

装饰器= 高阶函数 + 嵌套函数

装饰器

定义:装饰器本质是函数(装饰其他函数)就是为其他函数添加附加功能。
原则:

  • 1、不能修改被装饰函数的源代码
  • 2、不能修改被装饰函数的调用方式
    可以总结成一句话:悄无声息的为这个函数增加功能。
    一个简单的装饰器:
#我们想让test函数在打印出一条“大师兄”
def decoretor(func):
    def warpper(*args,**kwargs):
        print("大师兄")
        func()
    return warpper

@decoretor
def test():
    print("孙悟空")

test()

解读一下上面的代码,在我们的定义里 【装饰器本质是函数】,通过以上代码我们可以看出来,我们定义decoretor()本身就是函数。符合我们的定义。然后装饰器的原则是 【不能修改被装饰函数的源代码】【不能修改被装饰函数的调用方式】,很显然,我们没有在test中对其源代码进行修改,我们也没有改变test的调用方式。

解惑

我们按照【装饰器的知识储备】一一分析。

  • 函数即“变量”
    变量都会放在内存中。
    例如:x=1,1会存在在内存中,x会与内存形成一个映射关系,x指向内存1的地址。如下图所示
    内存图
    【函数即“变量”】我们可以理解函数在内存中的存放方式和x=1的是一样的,函数体在内存中,函数名与函数体一一映射。
    内存2
    我们如果想要运行这个函数,直接调用即可test(),但是调用函数跟调变量是有区别的,函数必须在函数名后面加上“()”,如果不加“()”,那么我们引用的则是test的内存地址值

    def test():
        print ("孙悟空")
    
    test()  # 孙悟空
    print(test)  # <function test at 0x000002546796F400>
    

    甚至可以更通俗的讲,我们把函数就赋值给变量,在我们调用变量的时,也就是在调用函数

    def test():
        print ("孙悟空")
    x = test
    x()#孙悟空
    
  • 高阶函数

    • 把一个函数名当做实参传递给另外一个函数
    • 返回值中包含函数名

    我们按照高阶函数的定义写一个函数

    def test1(func):
        return func
    
    def test2():
    	print ("孙悟空")
    
    x = test1(test2)
    x()#孙悟空
    

    看上面的代码,我们可以理解为test1()函数的返回值是test2这个函数的地址值,x=test1(test2)可以改写为x=test2,当我们打印x()的时候,相当于x()=test2(),相当于打印test2函数的返回值。所以记过为“孙悟空”
    这个时候我们可以模仿着写一个装饰器

    def decoretor(func):
        print("大师兄")
        func()
        return func
    def test():
        print ("孙悟空")
    
    decoretor(test)
    

    看这个结果符合我们的需求,在打出“孙悟空”之前打出"大师兄"这句话。看着想那么回事,我们没有改变test()函数源码,但是我们改变了函数的调用方式,所以这个看似像装饰器的函数,并不是我们想要的结果。
    那么我们再继续修改:

    def decoretor(func):
        print("大师兄")
        return func
    
    def test():
        print ("孙悟空")
    
    # x = decoretor(test)
    # test=x
    test = decoretor(test)
    test()
    

    这样我们就可以不改变源代码,不改变调用方式,就可以对test()函数进行修改。

写到这里,我们用了【函数即“变量”】,用了【高阶函数】,是不是我们就可以这样写装饰器了呢?不!【装饰器= 高阶函数 + 嵌套函数】,我们还没有用【嵌套函数】!

  • 嵌套函数
    在函数体内,使用def再声明一个函数。
    def test1():
        def test2():
        	pass
    
    通过嵌套函数,我们把上面代码再次进行修改
    def demo(func):
        def decoretor():
            print("大师兄")
            func()
        return decoretor
    
    def test():
        print ("孙悟空")
    
    test = demo(test)
    test()
    
    python的装饰器原理就是这样,但是这个我们头开始的代码不一样,头开始的代码中带有@,而我们现在的代码没有@,其实@是python为我们提供的一个语法糖,将@放在待修饰的函数上面,这样我们的调用的时候就不用写【test = demo(test)】,直接在下面调用函数即可

讲完这几个之后,我们在往回看看上面写的装饰器,想必大家已经豁然开朗了吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值