龙空技术网

闭包究竟是个啥?超简单闭包理解

学习不能停止我的脚步 116

前言:

今天小伙伴们对“闭包解决”都比较关注,我们都想要剖析一些“闭包解决”的相关内容。那么小编同时在网络上搜集了一些对于“闭包解决””的相关知识,希望同学们能喜欢,各位老铁们快快来学习一下吧!

我也是自学的小白,看到这个名词之后我觉得我好像理解了,但是跟着实际操作之后仿佛又蒙了,这一刻我似乎想起了太极宗师张三丰问张无忌的那句话,你记住了嘛?

这一刻我既没记住名词的解释也没有看懂实例操作,终于在冲了好久的浪之后我给闭包整懂了。

什么样的函数能称之为闭包呢?只要有以下特征都可以称之为闭包:

一个函数中声明了另一个函数并返回,能够引用非全局变量的变量。

再让我们看看百度的说明,嗯好像比我说的更加简洁有力。

闭包就是能够读取其他函数内部变量的函数。

那么,这样在一个函数中声明另一个函数有什么好处呢?或者说任何一种概念被发明出来都是为了解决问题的,那么闭包这种行为解决了什么问题呢?

可以外部访问函数内部变量

内部函数可以访问外层函数变量

def 外层函数A():
   a = "我是外层函数变量小a"
   def 内层函数B():
       nonlocal a
       print(a)
   return bar    
x=foo()
x()  #"我是外层函数变量小a"

局部变量可以常驻内存

#常驻内存了,对变量自加不会被清理
def 外层函数A():
   a = 0
   def 内层函数B():
       nonlocal a
       a+=1
       print(a)
   return bar    
       
x=foo()    
x()   #1
x()   #2
x()   #3
x()   #4

常驻的是局部变量,防止了污染变量命名

当然了有好处也有坏处,天下没有任何一门功夫是六边形的,他的缺点自然是:

会造成内存泄漏(有一块内存空间被长期占用,而不被释放)

当然了,相对于抽象的说法和概念,在实际中闭包到底能解决什么问题呢?

下面以一个实例来看看闭包到底怎么解决问题的。

from threading import Timer
import time

# 定义总共输出几次的计数器
count = 0
def print_time():
   print("当前时间:%s" % time.ctime())
   global count
   count += 1
   # 如果count小于10,开始下一次调度
   if count < 10:
       t = Timer(1, print_time)
       t.start()
# 指定1秒后执行print_time函数
t = Timer(1, print_time)
t.start()

上面的例子时一个简单计数器,每经过1秒,变量count便会+1,最终在count 小于10的时候进行重置。

发现这段代码的问题了吗,那就是使用了全局变量count,要说编程最最痛苦的事情之一就是变量命名,要信雅达可太难了,但是好名字是有限的,如果放在全局变量中那就很难受了,别人要是也有使用了这个变量的命名就会造成冲突。

那么如何使用闭包的概念对他进行改造呢

# 改闭包
# 定义总共输出几次的计数器

def time_count():
   count = 0
   
   def print_time():
       nonlocal count      #要么使用nonlocal声明变量不是本地的才可以有调用
                           #或者可以将count=[0]  count[0]+=1  成为列表时为引用类型懂吧
       print("当前时间:%s" % time.ctime())
       print(count)
       count += 1
       # 如果count小于10,开始下一次调度
       if count < 10:
           t = Timer(1, print_time)
           t.start()
   return print_time
print_time=time_count()
# 指定1秒后执行print_time函数
t = Timer(1, print_time)
t.start()

看看,这就是闭包的好处,正常来说函数内部的变量用完就会被清理掉,但是有了闭包的存在,可以让函数内部的变量常驻,这样计数器进行计数就成为了可能,而且这还是一个局部变量不会污染全局。



标签: #闭包解决 #闭包 定义