一道必须迈过去的坎------Python装饰器介绍

装饰器背景:   在不改变原函数代码,  且保持原函数调用方法不变的情况下,  给原函数增加新的功能  

                    (或者给类增加新属性和方法)

核心思想:     一个函数(或者类) 去装修 一个旧函数 (或者类)   , 造出一个新函数(或者新类)


尽量简单代码, 逐步理解,  装饰器原型:

  • Python万物皆对象, 可以随意赋值使用

def func():
        print("第三: ","我是一个函数的输出结果")
a = 1
print("第一: 我是一个变量 ",a)
a = func                              #将函数名赋值给变量
print("第二: 我是一个函数名 ",a)
a()

>>>第一: 我是一个变量 1
>>>第二: 我是一个函数名 <function func at 0x000000000220AAE8>
>>>第三: 我是一个函数的输出结果


  • 变量作用域

# ###根据 LEGB原则, 内函数使用外函数的局部变量
def outer():
        a = 0
      print("我是外部函数的 a:",a)
        def inner():
        print("我是内部函数打印的 a:",a)
        
>>>我是外部函数的 a: 0
>>>我是内部函数打印的 a: 1
# ###引入 nonlocal, 内函数可以修改外函数
def outer():
      a = 0
      print("我是外部函数的 a:",a)
      def inner():
        nonlocal a
        a += 1
        print("我是内部函数加工过的 a:",a)
        
>>>我是外部函数的 a: 0
>>>我是内部函数加工过的 a: 1


  • 闭包( 延长局部变量生存时间 )

# ### 内函数  夹带  外函数的局部变量
def outer():
      a = 0
      print("我是外部函数打印的 a:",a)
      def inner():
        print("我是内部函数打印的 a:",a)
      return inner
 
res = outer()                            #res接收的是一个函数名
print("我是返回出来的内函数名: "res)
res()
 
>>>我是外部函数打印的 a: 0
>>>我是返回出来的内函数名: <function func at 0x000000000220AAE8>
>>>我是内部函数打印的 a: 0
# ### 内函数  夹带  修改后的  外函数的局部变量
def outer():
      a = 0
      print("我是外部函数打印的 a:",a)
      def inner():
        nonlocal a
        a += 1
        print("我是内部函数修改过的 a:",a)
      return inner
 
res = outer()                            #res接收的是一个函数名
print("我是返回出来的内函数名: "res)
res()
 
>>>我是外部函数打印的 a: 0
>>>我是返回出来的内函数名: <function func at 0x000000000220CA97>
>>>我是内部函数修改过的 a: 1


  • 函数名可以当做参数传递

# ### 新函数对旧函数修饰
def old():
    print('我是 旧函数')     
def new(f):
    print('我是 新函数, 我可以输出 旧函数')
    f()   
new( old )                          #把旧函数名当做参数, 传递给新函数, 在新函数内产生变化

>>>我是 新函数, 我可以输出 旧函数
>>>我是 旧函数


  • 装饰器原型 

# ### 利用闭包,将函数名当参数传递
def outer(f):
      def inner():
        print("我是外部传进来的old :",f)
        f()
        print("我是修饰工,我在旧函数后显示")
      return inner
  
def old():
      print("我是旧函数")

print("我是最初的old: ",old)                         
print("我是返回出来的内函数inner: ",outer(old))                      #outer把函数名old当参数传回函数内部进行加工, 把函数名inner返回

old = outer(old)                                                   #实际上, 旧函数名old已被重新赋值为inner
print("我不是原来的old了 ",old)
old()                                                                 #经过改造, 虽然调用结果不变, 但是运行结果已变化


>>>我是最初的old: <function old at 0x00000000021CAA60>
>>>我是返回出来的内函数inner:  <function outer.<locals>.inner at 0x00000000021CAAE8>
>>>我不是原来的old了  <function outer.<locals>.inner at 0x00000000021CAAE8>
>>>我是外部传进来的old : <function old at 0x00000000021CAA60>
>>>我是旧函数
>>>我是修饰工,我在旧函数后显示


  • 装饰器 

# ### 用 @outer 修饰
def outer(f):
      def inner():
        print("我是外部传进来的old :",f)
        f()
        print("我是修饰工,我在旧函数后显示")
      return inner
@outer                                       #实际上,将  old = outer(old)  这句改成 @outer, 放在old函数上方
def old():
      print("我是旧函数")
                                                 
old()                                                                 


>>>我是外部传进来的old : <function old at 0x00000000021CAA60>
>>>我是旧函数
>>>我是修饰工,我在旧函数后显示


猜你喜欢

转载自blog.51cto.com/dldxzjr/2378274