• 一道好题


    一道好题

    题目如下:

    def f():
        l = []
        for i in range(4):
            def a(x):
                return x * i
    
            l.append(a)
        return l
    
    
    print([e(2) for e in f()]) # [6, 6, 6, 6]
    

    代码可以翻译成这样:

    def f():
        l = []
        for i in range(4):
            def a(x):
                return x * i
    
            l.append(a)
        return l
    
    
    l_curr = []
    for e in f():
        l_curr.append(e(2))
    print(l_curr)
    

    代码的执行过程如下:

    • 代码从上到下执行,进入函数f()

    • 初始化空列表l

    • 进入for循环

    • i=0,执行l.append(a)

      python调用函数时加括号表示调用函数的最终执行结果,不加括号表示调用函数对象,所以这里列表追加的时函数对象。此时l=[<function f.<locals>.a at 内存地址1>]

    • i=1,执行l.append(a)

      此时l=[<function f.<locals>.a at 内存地址1>,<function f.<locals>.a at 内存地址2>]

    • i=2,执行l.append(a)

      此时l=[<function f.<locals>.a at 内存地址1>,<function f.<locals>.a at 内存地址2>],<function f.<locals>.a at 内存地址3>

    • i=3,执行l.append(a)

      此时l=[<function f.<locals>.a at 内存地址1>,<function f.<locals>.a at 内存地址2>],<function f.<locals>.a at 内存地址3>,<function f.<locals>.a at 内存地址4>

    • 函数f()执行完毕,return l

      此时l=[<function f.<locals>.a at 内存地址1>,<function f.<locals>.a at 内存地址2>],<function f.<locals>.a at 内存地址3>,<function f.<locals>.a at 内存地址4>

    • 初始化空列表l_curr

    • 进入for循环,开始遍历f()

      此时的f()是带括号的,所以引用的是最终返回的列表

    • 遍历第一个元素<function f.<locals>.a at 内存地址1>,执行2 * 3 = 6,这个函数存储的ii的引用,此时的i=3

    • 遍历第二个元素<function f.<locals>.a at 内存地址2>,执行2 * 3 = 6,这个函数存储的ii的引用,此时的i=3

    • 遍历第三个元素<function f.<locals>.a at 内存地址3>,执行2 * 3 = 6,这个函数存储的ii的引用,此时的i=3

    • 遍历第四个元素<function f.<locals>.a at 内存地址4>,执行2 * 3 = 6,这个函数存储的ii的引用,此时的i=3

    • 遍历完毕,返回列表l_curr=[6, 6, 6, 6]

    类比

    def f():
        l = []
        for i in range(4):
            def a(x, i=i):
                return x * i
    
            l.append(a)
        return l
    
    
    l_curr = []
    for e in f():
        l_curr.append(e(2))
    print(l_curr)
    

    区别是:def a(x, i=i)

    在这个程序中,函数f()中的列表l每次追加的函数a中存储的i当前的i值,而不是引用。所以四次的i值分别为0, 1, 2, 3

    所以最终的结果为l_curr=[0, 2, 4, 6]

  • 相关阅读:
    IntStack(存放int型值,带迭代器) 附模板化实现 p406
    Mule自带例子之stockquote
    Mule自带例子之loanbroker-simple
    Mule自带例子之flight-reservation
    hsqldb使用
    基于memcached中命令分析函数tokenize_command改造的split函数
    Memcached-1.4.4启动参数——手动设置chunk大小的上限
    Memcached源码分析——process_command函数解析
    Memcached源码分析——hash
    Memcached源码分析——slab的初始化
  • 原文地址:https://www.cnblogs.com/junsircoding/p/15664894.html
Copyright © 2020-2023  润新知