zoukankan      html  css  js  c++  java
  • 对于python 作用域新的理解

    今天看Python习题,看到如下题目

    def num():
        return [lambda x: i*x for i in range(4)]
    print([m(2) for m in num()])  # 求输出结果是什么

    我看了半天才明白这应该是一个列表生成式,列表中的元素为四个匿名函数,我本以为每个匿名函数应该是不一样的,因为他们的 i 不一样,所以应该返回的结果也会不同。可当我在命令行输出测试后才发现,完全不是这么回事啊!下面是输出结果

    [6, 6, 6, 6]  # 是真的6啊

    后来去网上搜索了一下才知道,原来是作用域的问题,看来我Python作用域没有学好啊,这个匿名函数中的作用域和外层的循环作用域是不同的,匿名函数的引用了外层作用域变量 i ,当匿名函数被调用时,会输出 i * x,但是 i 在匿名函数的作用域中是不存在的,所有只能想外层作用域寻找,也就是for循环的作用域,但是此时循环早就已经结束了,i 也不再是当时生成该匿名的 i 了,现在的 i 已经是循环到最后一层固定不变的 i 了,也就是 i = 3, 所有匿名函数中的返回值就都是一样的了,即 3 * x。

    如果还是不懂,可以将生成式转换为普通函数。如下

    def num():
        L = []
        for i in range(4):
            def lambda_(x):
                return i * x  # 该作用域内没有 i 变量,需要找寻上层作用域的 i 变量
            L.append(lambda_)  # 追加进列表的函数他们的返回值是 i * x,并不是0x,1x,2x,3x,变量还处于引用关系阶段
        return L
    
    lambda_list = num()
    
    L = []
    for lambda_ in lambda_list:
        result = lambda_(2)
        L.append(result)
    
    print(L)

     python 的作用域都有legb规则,即Local,Enclose,Global,Builtin,作用域的查找顺序是从内向外的。

  • 相关阅读:
    PAT乙级:1083 是否存在相等的差 (20分)
    PAT乙级:1082 射击比赛 (20分)
    PAT乙级:1084 外观数列 (20分)
    PAT乙级:1070 结绳 (25分)
    PAT乙级:1064 朋友数 (20分)
    JavaScript实现拖放效果
    Lesson2 Thirteen equals one
    PAT乙级:1076 Wifi密码 (15分)
    条件查询
    根据配置生成创始块文件和通道文件
  • 原文地址:https://www.cnblogs.com/welisit/p/10656905.html
Copyright © 2011-2022 走看看