Python每日一题

时间:2022-07-23
本文章向大家介绍Python每日一题,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

题目:如果理解 Python 中的闭包?

答案要点如下:

  1. 解释什么是 返回函数,这是像类似 JAVA 这样的静态语言所做不到的功能。即在函数中嵌套定义一个函数,而在外层函数可以返回内层函数名。简单示例如下:
def outer():
    def inner():
        print("inner")
    # 注意不要加 () ,不加括号表示返回的是一个函数整体,而加括号,表示返回的是函数执行的结果
    return inner 
  1. 闭包概念的基础就是基于 Python 中的 返回函数 的特性,它的要点:嵌套函数;内层使用外层非全局的变量。简单示例如下:
def outer():
    i = 10
    def inner():
        print(i)
    # 当我们在调用 outer() 函数时
    # 当执行到 return 语句时,整个函数执行完毕
    # 但此时,inner 函数体中还存在 outer 的局部变量 i 的引用
    # 这种称之为闭包
    return inner
  1. 闭包所体现的延迟绑定,当我们在外层有循环变量时,在内层使用可能不会出现我们预期的效果。下面代码的现象就是延迟绑定,即当我们在返回 inner 这个函数时,它里层的代码并没有执行,而当我们 print…for…in 去调用返回接受到的函数时,它才真正执行,而此时,i 的值已经是3了。这也告诉我们在闭包中,尽量不要使用循环变量。示例如下:
def outer():
    return [lambda x : x*i for i in range(1,4) ]

print([o(2) for o in outer()]) # [6, 6, 6]

# 如果对匿名函数不熟悉
# 上述代码可等价于
def outer():
    fn = []
    for i in range(1,4):
        def inner(x):
            return x*i
        fn.append(inner)
    return fn

print([o(2) for o in outer()]) # [6, 6, 6]
  1. 而如果一定要使用循环变量,也是可以解决的。解决思路是因为上述代码中,循环变量之所以没有一次一次生效,而是在最后生效,是因为它整体都在 inner 函数中。我们只需要用一个可立即执行的代码去承接循环变量,即可解决这一问题,比如我们用一个函数去承接它,示例如下:
def outer():
    return [lambda x, i=i : x*i for i in range(1,4) ]

print([o(2) for o in outer()]) # [2, 4, 6]

# 如果对匿名函数不熟悉
# 上述代码可等价于
def outer():    
    fn = []
    def f(i): # 在嵌套一个函数,让它执行,给 i 明确一个值
        def inner(x):
            return i*x
        return inner
    for i in range(1,4):
        fn.append(f(i))

    return fn

print([o(2) for o in outer()]) # [2, 4, 6]

愿关注我们的人都能找到

属于自己的皮球