什么是闭包
# 概念:内嵌函数引用了外层函数的变量然后返回内嵌函数就称之为闭包。# 总结一下,创建一个闭包必须满足以下几点:# 1. 必须有一个内嵌函数# 2. 内嵌函数必须引用外部函数中的变量# 3. 外部函数的返回值必须是内嵌函数
闭包的判断,外层打印执行函数f().__closure__,闭包返回内存地址,非 闭包返回None
x=1def f1(): x=1000 y=1 def f2(): print(x) print(y) return f2f=f1()#执行f2f()#返回内存地址, 判定是不是闭包print("f.__closure__:",f.__closure__)# (, | )x=2def f2(x): y=1 def f2(): print(x) print(y) return f2f=f2(2)#执行f2f()#返回内存地址, 判定是不是闭包print("f.__closure__:",f.__closure__)# ( | , | )def f3(): def f2(): x=1000 print(x) return f2f=f3()#执行f2f()#返回内存地址, 判定是不是闭包print("没有外部变量 f.__closure__:",f.__closure__)# 返回None |
闭包的作用,优缺点
# 闭包的作用# 1.使用闭包可以访问函数中的变量。# 2.可以使变量长期保存在内存中,生命周期比较长。# 优点:封装代码提高重用性,安全# 缺点:重点是函数运行后并不会被撤销,滞留内存# 闭包不能滥用,否则会导致内存泄露(内存无法释放),影响网页的性能。# 闭包使用完了后,要立即释放资源,将引用变量指向null。# 关于内存泄漏和内存溢出# 内存泄漏(Memory Leak)是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,# 造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。# 内存溢出就是你要求分配的内存超出了系统能给你的,系统不能满足需求,于是产生溢出。
几个案例
# 如下返回,返回的是三个结果,这三个结果是无法调用,能调用的只有函数,所以你必须返回函数def count(): fs = [] for i in range(1, 4): x=i*i fs.append(x) return fsprint(count())# f1, f2, f3 = count()# print(f1(), f2(), f3())# 返回三个函数的列表,直接把函数名添加进去即可def count(): fs = [] for i in range(1, 4): def f(m=i): return m * m fs.append(f) return fsf1, f2, f3 = count()print(f1, f2, f3)print(f1(), f2(), f3())def mul(): z=[lambda x:i*x for i in range(4)] return zprint([j(2) for j in mul()])# x是闭包变量,[6,6,6,6]def mul(): z=[lambda x,i=i:i*x for i in range(4)] return zprint([j(2) for j in mul()])
惰性计算
x=1def f1(): x=1000 y=1 def f2(): print(x) y return f2f=f1()#执行f2f()#返回内存地址, 判定是不是闭包print(f.__closure__)#返回内部x,yprint(f.__closure__[0].cell_contents)print(f.__closure__[1].cell_contents)#牛逼之处,惰性计算,想要的时候加个括号from urllib.request import urlopendef get(url): r=print(urlopen(url).read()) return rpy=get("http://www.baidu.com")def spi(url): def spider(): print(urlopen(url).read()) return spiderspider1=spi("http://www.baidu.com")#需要的时候执行spider1()print(spider1.__closure__)