python之闭包的实现

闭包的定义:

首先我们先给出闭包的概念,如果内部函数引用了外部函数作用域里的变量(非全局变量),则称这个内部函数以及用到的变量统称为闭包

在python中的闭包需要满足三个条件:

  • 必须是一个嵌套的函数。
  • 外层函数返回的是内层函数的函数名
  • 嵌套函数必须引用一个外部的非全局的局部自由变量。

可能这些东西听起来非常绕嘴,难以理解,下面我们举个例子。

def func_out(num):  #外层函数

    # 在函数内部再定义一个函数,并且这个函数用到了外边函数的变量,那么将这个函数以及用到的一些变量称之为闭包
    def func_in(num_in):    #内层函数

        print("在内层函数里, num_in is %d" % num_in)
        return num + num_in

    # 其实这里返回的就是闭包的结果
    return func_in  #这里返回就是内层函数名字func_in

# 给func_out函数赋值,这个20就是给参数num
pnum = func_out(20)
# 注意  这里的100其实给参数numb_in
print(pnum(100))

#注 意这里的200其实给参数numb_in
print(pnum(200))

让我们看看运行的结果:

在内层函数里, num_in is 100
120

在内层函数里, num_in is 200
220

在开发中,用到闭包可以提高的代码的复用率。下面我们举一个初中曾经学习的一次函数y=kx+b的例子

def line_conf(k, b):    #外层函数 发生函数嵌套
    def line(x):        #内层函数
        return k*x + b  #内层函数引用外层函数的变量 ,格式:y=kx+b
    return line         #返回内层函数名

line1 = line_conf(2, 1)  #  k=2 , b=1  -->y=2x+1
print(line1(7))          # y=7*2+1=15

line2 = line_conf(4, 5)  #  k=4, b=5     -->y=4x+5
print(line2(8))          #  y=4*8+5=37

上面的代码中,函数line与变量a,b构成闭包。在创建闭包的时候,我们通过line_conf的参数a,b说明了这两个变量的取值,这样,我们就确定了函数的最终形式(y = 2x + 1和y = 4x + 5)。
我们只需要变换参数a,b,就可以获得不同的一次函数的表达式。由此,我们可以看到,闭包也具有提高代码可复用性的作用。

如果没有闭包,我们需要每次创建直线函数的时候同时说明a,b,x。这样,我们就需要更多的参数传递,也减少了代码的可移植性。

除此之外,闭包也可以做装饰器用,比如计算某一个函数的运行时间

import time
def timer(func):
    def wrapper():
        start_time = time.time()    #开始时间
        func()                      #引用外层函数中的变量
        stop_time = time.time()     #结束时间
        print('run time is %f'%(stop_time-start_time))
    return wrapper

@timer      #定义修饰timer为装饰器
def fun():
    print('函数开始start-----')
    time.sleep(3)   #函数睡眠3秒钟
    print('函数结束end-------')

if __name__ == '__main__':
    fun()

看看运行的结果:

函数开始start-----
函数结束end-------
run time is 3.000939

下面我们总结点闭包的优点:

  • 避免使用全局变量
  • 提高了代码的复用率
  • 实现部分数据的隐藏
  • 可以提供更优雅的面向对象实现

闭包的缺点:

  • 消耗内存空间,造成内存泄漏 (因为内部引用外层的局部变量,没有及时释放)

参考文献:
Python中的闭包

猜你喜欢

转载自blog.csdn.net/weixin_38819889/article/details/86506128