Python常见面试题014.请说出下面的代码返回结果是什么?

python,常见,面试题,请说出,下面,代码,返回,结果,什么 · 浏览次数 : 36

小编点评

函数 `fun` 的逻辑是,它创建一个包含多个 lambda 函数的列表,并根据传入的 `d` 值选择其中一个函数执行。 **代码逻辑步骤:** 1. 定义一个列表 `nums`,并使用 `for` 循环在 `a` 到 `b` 之间的每个 `num` 创建一个匿名函数。 - `nums.append(lambda: num ** c)` 创建一个匿名函数,其中 `c` 是一个自变量。 - 每个匿名函数都会返回 `num` 的 `c` 次方。 2. 定义一个函数 `fun`,它接收 `a`、`b`、`c` 和 `d` 的参数,并返回一个包含多个匿名函数的列表。 3. 在 `fun` 的循环中,使用 `lambda` 关键字定义多个匿名函数,并将其添加到 `nums` 列表中。 - `nums[d]` 选择 `nums` 中对应位置的最后一个匿名函数。 4. 最后,调用 `fun` 的 `d` 个参数,并返回其结果。 **问题所在:** 由于 `num` 在循环中是不同的,所以在定义 lambda 函数时,`n` 的值会不同。因此,`fun` 的最终返回值并非按预期的那样,而是从 `nums` 中取出的最后一个匿名函数的返回值。 **解决方案:** 为了解决这个问题,我们可以使用 `lambda` 的 `n=num` 语句定义一个新的本地变量 `n`,并在 `lambda` 函数中使用 `n` 来访问 `num` 的值。这样,每个 lambda 函数都会使用相同的 `num` 值。

正文

示例代码

def fun(a, b, c, d):
    nums = []
    for num in range(a, b):
        nums.append(lambda: num ** c)
    return nums[d]()

print(fun(1, 5, 2, 0))
print(fun(1, 5, 2, 1))
print(fun(1, 5, 3, 1))
print(fun(1, 10, 2, 1))
  • 答案是







16
16
64
81

原因分析

  • 调用函数fun(1, 5, 2, 0)

  • 意味着

    nums = []
    for num in range(1, 5):
        nums.append(lambda: num ** 2)
    return nums[0]()
    
  • 所在列表nums中是多个匿名函数

  • 应该依次是

    lambda :1**2
    lambda :2**2
    lambda :3**2 #依次类推
    ...
    
  • 那按照我们的想法,nums[0]应该是lambda :1**2,调用应该得到1才是

    >>> demo1 = lambda :1**2
    >>> demo1()
    1
    >>> demo2 = lambda :2**2
    >>> demo2()
    4
    
  • 但结果并不是这样的,nums[0]()得到的结果是range()结束值=5-1时的4**2

  • 甚至从答案可以看出来nums[1]()也是

  • 依次类推,fun(1, 5, 3, 1)=>nums[1]()=>结束值5-1=4的三次方=>64


  • 所以规律是有了,道理何在?

  • 看下代码

    def fun(a, b, c, d):
        nums = []
        for num in range(a, b):
            nums.append(lambda: num ** c)
        return nums[d]()
    
  • 这是因为 num 不是 lambda 函数的内部变量,而是定义于外部作用域中的,并且 num 是在调用 lambda 时访问的——而不是在定义时访问。循环结束时 num 的值是 4 ,所以此时所有的函数都将返回 4**2 ,即 16

拓展

  • 那要如何才能符合我们的预期呢?nums[0]()nums[1]()是不一样的

  • 你可以将值保存在 lambda 局部变量,以使其不依赖于全局 num 的值

    def fun(a, b, c, d):
        nums = []
        for num in range(a, b):
            nums.append(lambda n=num: n ** c) # n = num
        return nums[d]()
    
    print(fun(1, 5, 2, 0)) 
    print(fun(1, 5, 2, 1))
    print(fun(1, 5, 3, 1))
    print(fun(1, 10, 2, 1))
    # 依次输出
    1
    4
    8
    4
    
  • 以上 n=num 创建了一个新的 lambda 本地变量 n,并在定义 lambda 时计算其值,使其与循环当前时点的 num 值相同。这意味着 n 的值在第 1 个 lambda 中为 0 ,在第 2 个 lambda 中为 1 ,在第 3 个中为 2,依此类推

以上参考

https://docs.python.org/zh-cn/3.9/faq/programming.html#why-do-lambdas-defined-in-a-loop-with-different-values-all-return-the-same-result

与Python常见面试题014.请说出下面的代码返回结果是什么?相似的内容:

Python常见面试题014.请说出下面的代码返回结果是什么?

示例代码 def fun(a, b, c, d): nums = [] for num in range(a, b): nums.append(lambda: num ** c) return nums[d]() print(fun(1, 5, 2, 0)) print(fun(1, 5, 2, 1

Python常见面试题001-005,涉及深浅拷贝、MRO、函数可变参数、作用域、is和==的区别等

Python常见面试题001-005 参考资料 https://github.com/taizilongxu/interview_python https://github.com/hantmac/Python-Interview-Customs-Collection https://github.

Python常见面试题006 类方法、类实例方法、静态方法有何区别?

006. Python中类方法、类实例方法、静态方法有何区别? 全部放一个里面篇幅过大了,就拆分成1个个发布 示例代码 class Human: def __init__(self, name): self.name = name def say(self): print(f'我的名字是{self.

Python常见面试题007. 谈谈Python中__init__和__new__的区别

007. 谈谈Python中__init__和__new__的区别 python中关于dunder method双下方法,或magic method魔术方法的描述多在 https://docs.python.org/zh-cn/3.9/reference/datamodel.html#special

Python常见面试题008. 谈谈python中的解包

008. 谈谈python中的解包 这是个简单的知识点,但有的学员并不理解 unpacking解包 解,对应的是*或者**,也有自动解包之说 包对应的可迭代对象 自动解包 赋值的demo a,b = [1,2] print(a) # 1 print(b) # 2 将容器里面的元素逐个取出来分别赋值

Python常见面试题011. 如何在Python中动态创建类?

011. 如何在Python中动态创建类? 说在前面 答案是type 你印象中的type是用来查看对象的类型的 li = [] type(li) # 得到list 对自定义的类是这样的 class Person: pass wuxianfeng = Person() type(wuxianfeng)

Python常见面试题009. 元组和列表有什么区别

009. 元组和列表有什么区别 这个题是简单的,但要拿满分或者说高分不容易 相同点 | 共性 | 说明 | | | | | 可以存放任意元素 | 一般都放同类型 | | 支持索引访问 | 甚至是负数 | | 支持切片操作 | | | 逗号分隔元素 | | | 都是有序集合(容器) | | | 可以随

Python常见面试题010. Python的int占多大内存?

010. Python的int占多大内存? 示例代码 import sys a = 0 print(a.__sizeof__()) # 24 print(sys.getsizeof(a)) # 24 所以答案是24?并不是!看下面 import sys b = 1 print(b.__sizeof_

Python常见面试题012. 可迭代对象和迭代器有啥区别?

012. 可迭代对象和迭代器有啥区别? 2者不是一回事(废话) 比如 from collections.abc import Iterable,Iterator print(isinstance([1, 2], Iterable)) # True 列表是可迭代对象 print(isinstance(

Python常见面试题013.请说出下面的代码返回结果是什么?

013.请说出下面的代码返回结果是什么? *的坑;简单题 参考:https://docs.python.org/zh-cn/3.9/library/stdtypes.html#typesseq 示例代码 lists = [[]] * 3 lists[0].append(1) 请问lists此时是什么