zoukankan      html  css  js  c++  java
  • 当列表推导式遇到lambda(匿名函数)

     

    Python这么优雅的语言,我也是醉了......

    事情由一段代码引发,请看:

     

    上述的列表推导式+lambda表达式+for循环,他们碰撞出来的结果搞的人晕头转向,咱们逐步来分析一下他们到底是个什么鬼。

    lambda表达式可以表示成:

    def func(x):
    return x*i
    加上for循环:

    for i in range(10):
    def func(x):
    return x*i
    加上列表推导式:  # 注释一

    到此,就可以看清楚他的结构了,funcs函数里面形成了一个闭包
    闭包的两个特性:

    ①、内部函数使用外部函数的变量(不对外部函数的变量进行重新赋值)

    ②、外部函数 return 内部函数的函数名(其实是返回内部函数的内存地址)

    对上面的函数进行简化:去掉for循环,使用单个变量代替,去掉 列表 li 直接返回内部函数名,它就变成了下面这个样子

    简单理解:闭包 = 内部函数 + 环境变量

    闭包的特性:当内部函数返回的时候,会把连同内部函数定义时候的环境变量一同返回

    了解了闭包,在来看结果为什么全都是18,而不是预期结果:

    ①区分内部函数的定义和调用:

    当我们只到是定义了外部和内部函数,调用了外部函数,并未调用内部函数,也就是到注释一

    for循环的作用就是创建10个函数,最后 i 的取值是9

    所以我们获得了类似下面的图谱:

    当我们进行内部函数调用的时候,此时的情形是:

    有一个包含10个函数的列表,变量 i=9

    再加上闭包的特性,i 会随着内部函数的一同返回,所以调用依次内部函数的时候,情形就成了下面这样:以调用第1个函数为例

     

    所以结果就成了 2 * 9 = 18

    再调用别的内部函数都是如此逻辑。

    知乎中此问题的回答者 @Op小剑 提到了延迟绑定

    匿名函数的 i 并不是依次顺序指向0,1,2,...的,因为在迭代的过程中,创建匿名函数→创建完成后→才去找i 指向的值。

    对上图做了很好的诠释

    lambda不传参只有返回值的形式


    当我们将表达式修改为下面的样子,预期结果就出现了:


    修改到列表推导式+lambda表达式就是下面的情况:

    此时调用的情形就像下面的图谱:

    当你的才华还撑不起你的野心的时候,你就应该静下心来学习; 当你的能力还驾驭不了你的目标时,就应该沉下心来历练。
  • 相关阅读:
    django项目部署服务器后无法发送邮箱 错误信息:Connection unexpectedly closed
    python
    python
    获取当前时间减去 xx时,xx分,xx秒
    Python之List和Tuple类型(入门3)
    AndroidProjects个人项目归纳
    Android面试问题收集总结
    Python变量和数据类型(入门2)
    Python简单介绍以及Python环境搭建(入门1)
    Andriod ADB Interface驱动安装失败Configure USB Debug for Android
  • 原文地址:https://www.cnblogs.com/huhuxixi/p/10392136.html
Copyright © 2011-2022 走看看