ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

面试题-python 什么是闭包(closure)?

2021-03-04 13:32:49  阅读:142  来源: 互联网

标签:闭包 面试题 return 函数 temp python inner def


前言

前面学了装饰器,那么闭包和装饰器有什么区别呢?
闭包传递的是变量,而装饰器传递的是函数对象,只是传的参数内容不一样,闭包的概念包含了装饰器,可以说装饰器是闭包的一种,它只是传递函数对象的闭包。

先看一个面试题

先看一个经典的面试题,很有代表性, 运行以下代码会输出什么呢?为什么会是这种结果?

def fun():
temp = [lambda x: i*x for i in range(4)]
return temp

for everyLambda in fun():
print(everyLambda(2))

运行结果

6
6
6
6

运行的结果是4个6 ,并不是我们想的 :0, 2, 4, 6。上面的代码用到了列表推导式,还有个匿名函数lambda,直接去阅读不太好理解,可以把匿名函数转成自己定义一个函数.
于是上面的代码等价于:

"""
def fun():
temp = [lambda x: i*x for i in range(4)]
return temp

for everyLambda in fun():
print(everyLambda(2))
"""

def fun():
temp = []
for i in range(4):
def inner(x):
return i*x
temp.append(inner)
return temp

for everyLambda in fun():
print(everyLambda(2))

为了更好的理解,可以先去掉外面的一层fun()

temp = []
for i in range(4):
def inner(x):
return i*x
temp.append(inner)

for everyLambda in temp:
print(everyLambda(2))

这里只定义了一个函数 inner(), 有 2 个变量,i 是函数外部的变量,x 是函数内部的变量。
现在问题的关键在理解函数外部变量和函数内部变量的区别了, 接下来再看一个简单的例子

a = 1

def myfunc(b):
return a+b

print(myfunc(100))
a = 2
a = 3
print(myfunc(100))
print(myfunc(100))

运行结果:101   103   103
也就是函数外部变量a是可变的,后面给a重新赋值了,会替换前面的值。上面的 inner(x) 函数也是一样,外部变量 i 的值是0, 1, 2, 3变化,最后的3 会覆盖前面的值,所以得到的结果都是6
如何解决上面的问题,接下来就是要说的闭包的概念了!

什么是闭包?

闭包就是外部函数中定义了一个内部函数,当外部函数返回内部函数对象(注意是函数对象)时,程序接收了内部函数的定义(此时并未被执行),当再次执行这个返回值时,这个被返回的函数才能被执行。
创建一个闭包必须满足以下几点:

  • 必须有一个内嵌函数

  • 内嵌函数必须引用外部函数中的变量

  • 外部函数的返回值必须是内嵌函数

闭包和装饰器的区别:闭包传递的是变量,而装饰器传递的是函数,除此之外没有任何区别,或者说装饰器是闭包的一种,它只是传递函数的闭包。
以下是闭包的一个标准示例:

def outer(age):
def inner(name):
print("my name is %s. my age is %s." % (name, age))
return inner

demo = outer("18")
demo("yoyo")
# 运行结果:my name is yoyo. my age is 18.

上面的问题,用闭包来解决

# 闭包
def temp(i): # 一个外层函数
def inner(x): # 内层函数
return i*x
return inner

a = []
for i in range(4):
a.append(temp(i))
print(a)

for j in a:
print(j(2))

运行结果

[<function temp.<locals>.inner at 0x000002A8EE929AE8>, 
<function temp.<locals>.inner at 0x000002A8EE929B70>,
<function temp.<locals>.inner at 0x000002A8EE929BF8>,
<function temp.<locals>.inner at 0x000002A8EE929C80>]
0
2
4
6

使用列表推导式

# 闭包
def temp(i): # 一个外层函数
def inner(x): # 内层函数
return i*x
return inner

def fun():
temps = [temp(i) for i in range(4)]
return temps

for everyLambda in fun():
print(everyLambda(2))

这样就可以得到我们的预期结果:0 2 4 6

通过上面的案例就可以了解到闭包的作用了,它保存了函数的外部变量,不会随着变量的改变而改变了。

 

来源:https://mp.weixin.qq.com/s/vCR8ZzYtu3eUP44Z_Vmwzg

标签:闭包,面试题,return,函数,temp,python,inner,def
来源: https://www.cnblogs.com/liuyanhang/p/14479728.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有