定义
在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了一个闭包。
一般情况下,在我们认知当中,如果一个函数结束,函数的内部所有东西都会释放掉,还给内存,局部变量都会消失。但是闭包是一种特殊情况,如果外函数在结束的时候发现有自己的临时变量将来会在内部函数中用到,就把这个临时变量绑定给了内部函数,然后自己再结束。
在计算机科学中,闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。闭包在运行时可以有多个实例,不同的引用环境和相同的函数组合可以产生不同的实例
比如我们要计算两数相加,那对于一般情况下或者说普通函数可以这样定义:
def sum(a,b):
return a+b
print(sum(3,4))
那对于闭包函数呢,可以使用以下方式进行定义:
def sum(a):
def add(b):
return a +b
return add
对于闭包函数如何调用呢?
num2 = sum(2)
num3 = sum(2)
print (type(num2))
print (num3(4))
运行结果截图如下:
可知,num2返回的是一个方法。
Tips:
这里简单的说明一下单独是使用add
是属于函数名称或者说函数的引用,如果函数后面带括号,如add()
这个属于函数的调用。
如何编写闭包函数
那如何写一个闭包函数呢?
其实也是有规律的,就是 外层函数的返回值是里层函数的函数名 。
最后载通过一个例子进行说明。
如果我们要计算一个表达式的值,比如:a*x+b=y
对于普通函数,我们一般会这样定义:
def func1(a,b,x):
....
那对于闭包函数呢?
我们可以先按套路写好框架,如下:
def a\_line():
def arg\_y():
return
return arg_y
首先我们要考虑最外一层函数的变量,然后是里层函数的变量,接着是里层函数的返回值。
a=3,b=5
x=10,y=?
比如,我们计算的时候,在给出a,b的值后,还需要知道x的值,才可以计算出y的值
那根据这样的一个计算顺序,我们可以确定:外层函数的变量是(a,b),里层函数的变量是 x ,里层函数的返回值就是我们要计算的结果 :a*x+b=y
那函数就可以这样写了:
def a\_line(a,b):
def arg\_y(x):
return a \* x + b
return arg_y
这里 我们还可以将代码优化一下,就是将里层函数转换为lambda表达式:
def a\_line(a,b):
# def arg\_y(x):
# return a \* x + b
return lambda x:a\*x+b
return arg_y
调用函数,得到的运行结果为:
line1 = a_line(3,5)
print(line1(10))
print (line1(20))
闭包作用
个人认为使用闭包的好处,就是减少了全局变量的使用,在闭包中环境变量可以持久保存相当于全局变量,在编码中应该要减少使用全局变量。其次使用闭包,可以实现轻量级的接口封装,提高代码可复用性,比如:
def line(a, b):
def xy(x):
return (x,a\*x + b)
return line
这个函数实现了对求一次函数的定义和求坐标的封装,我们可以通过line定义一个一次函数(line1=line(4,5)),然后通过line1(x)打印出坐标,与普通函数相比我们不需要频繁地传入a,b,x这些参数
闭包的注意事项
使用闭包是注意不要对环境变量赋值,这会被认为是局部变量比如:
def curve\_pre():
a = 10
def curve(x):
a = 20
return a \* x \* x
return curve
print(curve_pre()(2))
print(curve_pre().__closure__)
输入结果:
80
None
如果我想对a赋值我们要怎么做呢?我们可以使用nonlocal
def curve\_pre():
a = 10
def curve(x):
nonlocal a
b = 20
a = 20
return a \* x \* x
return curve
print(curve_pre()(2))
print(curve_pre().__closure__)
print(curve_pre().__closure__[0].cell_contents)
结果:
80
(<cell at 0x0000007E40270B28: int object at 0x00000000512D02F0>,)
10
nice生活:https://www.jianshu.com/p/84e7ed4a35c4
Jane93:https://www.jianshu.com/p/f4f78766ba1b
IT入门 感谢关注 | 练习地址:www.520mg.com/it
学好 Python 不论是就业还是做副业赚钱都不错,但要学会 Python 还是要有一个学习规划。最后大家分享一份全套的 Python 学习资料,给那些想学习 Python 的小伙伴们一点帮助!
一、Python所有方向的学习路线
Python所有方向路线就是把Python常用的技术点做整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。
二、学习软件
工欲善其事必先利其器。学习Python常用的开发软件都在这里了,给大家节省了很多时间。
三、全套PDF电子书
书籍的好处就在于权威和体系健全,刚开始学习的时候你可以只看视频或者听某个人讲课,但等你学完之后,你觉得你掌握了,这时候建议还是得去看一下书籍,看权威技术书籍也是每个程序员必经之路。
四、入门学习视频
我们在看视频学习的时候,不能光动眼动脑不动手,比较科学的学习方法是在理解之后运用它们,这时候练手项目就很适合了。
五、实战案例
光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。
六、面试资料
我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!