day05 - 闭包、装饰器

一、闭包

  • 满足闭包的条件
    1.一个函数定义中嵌套另一个函数的定义
    2.内函数中往往会用到外函数中的参数,无论是传递的还是外函数的局部变量(内函数可以访问的外部变量)
    3.外函数的返回值为内函数名(函数的引用(指向))

    ①python中定义函数的过程相当于将函数名(也就是变量名)指向一段代码,即函数体
    ②内函数与外函数共享外函数中的变量值
def line_conf(a, b):
    def line(x):
        return a*x + b   #内函数共享外函数的局部变量
    return line

line1 = line_conf(1, 1)
# 此时line1指向line指向的函数体,即line1是一个函数名
line2 = line_conf(4, 5)
#同上
print(line1(5))
#相当于调用line函数
print(line2(5))

二、装饰器
*介绍:*通过装饰器,在原来函数的基础上增添功能,不用修改原函数,也不用改变之前调用函数的调用方式(不改变原函数的情况下修改原函数)

  • 对无参数无返回值的函数进行装饰
#无装饰器
#定义函数
def function():
    print('我是函数……')
#调用函数
function()

#使用装饰器
def test(fun):
    print('我是个装饰器……')
    def start_fun():
        fun()
        print('函数执行完成')
    return start_fun
        
@test    # 相当于 function = test(function) 
def function():
    print('我是函数……')
function()


装饰器的功能其实通过改变函数名(变量名)的指向来实现的
函数名原先指向函数体,通过装饰器,函数名指向闭包的内部函数名所指的代码块(即调用原来的函数相当于调用闭包的内部函数)

  • 对具有参数的函数进行装饰
def test(fun):
    print('我是个装饰器……')
    def start_fun(a,b):
        fun(a,b)
        print('函数执行完成')
    return start_fun
        
@test    # function = test(function) 
def function(a,b):
    print('%d+%d=%d'%(a,b,(a+b)))
function(1,2)
  • 对不定长参数的函数进行装饰
#通用方式
def test(fun):
    print('我是个装饰器……')
    def start_fun(*args,**kwargs):  #定义函数时传递的不定长参数
    	fun(*args,**kwargs)  #执行函数时传递的实参是对不定长参数的解包
        print('函数执行完成')
    return start_fun
        
@test    # function = test(function) 
def function(*args,**kwargs):
    print('%d+%d = %d'%(args[0],args[1],args[0]+args[1]) )
function(1,2)


①对于有参数的函数进行装饰时,一般选择用不定长参数来接受参数值,比较通用
②当args和kwargs不为空时,*args和**kwargs相当于对元组args和字典kwargs解包

  • 对具有返回值的函数装饰
def test(fun):
    print('我是个装饰器……')
    def start_fun(*args,**kwargs):
        return fun(*args,**kwargs)
    return start_fun
        
@test    # function = test(function) 
def function(*args,**kwargs):
    return args[0]+args[1]
function(1,2)


函数中的return具有终止函数并返回值的功能

  • 同一个装饰器对多个函数装饰
def test(fun):
    print('我是个装饰器……')
    def start_fun(*args,**kwargs):
        return fun(*args,**kwargs)
    return start_fun
        
@test    # function1 = test(function1) 
def function1(*args,**kwargs):
    return args[0]+args[1]
print(function1(1,2))

@test    # function2 = test(function2) 
def function2(*args,**kwargs):
    return args[0]-args[1]
print(function2(1,2))

  • 同一装饰器对不同函数装饰时,会单独复制一份内存空间,用来存储每个使用装饰器的函数的函数名(变量名)所指向的闭包中内函数的代码块
  • 不同装饰器对同一函数装饰
def test1(fun):
    print('我是个装饰器1……')
    def start_fun(*args,**kwargs):
        return fun(*args,**kwargs)
    return start_fun

def test2(fun):
    print('我是个装饰器2……')
    def start_fun(*args,**kwargs):
        return fun(*args,**kwargs)
    return start_fun
        
@test1     
@test2    # function2 = test2(function2) 
def function2(*args,**kwargs):
    return args[0]-args[1]
print(function2(1,2))


执行顺序:test2函数,test1函数,function2函数
即离被修饰函数最近的,依次往外开始执行

  • 带有参数的装饰器
def test1(num):
    print(num+1)
    def test(fun):
        print('我是个装饰器……')
        def start_fun(*args,**kwargs):
            return fun(*args,**kwargs)
        return start_fun
    return test
        
@test1(2)    
#执行test1函数
# 将test1的返回值(是一个函数名)当作装饰器用来装饰function  相当于function1 = test(function1) 
def function1(*args,**kwargs):
    return args[0]+args[1]
#调用函数
print(function1(1,2))
发布了30 篇原创文章 · 获赞 0 · 访问量 279

猜你喜欢

转载自blog.csdn.net/qq_36334897/article/details/104956206