1、问题

有这么一个小面试题:

看下面代码请回答输出的结果是什么?为什么?

result = [lambda x: x + i for i in range(10)]
print(result[0](10))

2、解答

当你看到这篇文章的时候如果不知道这个知识点肯定会拿去直接运行,输出的结果是什么呢?

结果是:19

通过result[0~9](10)结果都是19就,懵逼了吧~~

想知道这个我们先看几个知识点

2.1、列表生成式

顾名思义,列表生成式就是一个用来生成列表的特定语法形式的表达式。

语法格式:

[expression for iterable_var in iterable]

工作过程:

  • 迭代iterable的每个元素
  • 把迭代的值赋值给iterable_var,然后通过expression的表达式进行计算得到一个新的值
  • 最后把所有expression的值以新列表的形式返回

工作过程类似于:

L = []

for i in range(10):
# 举例expression 表达式 iterable_var * 5 ,最后把这个结果加到列表中
L.append(i * 5)

点到为止,我们来看下我们的这个小面试题

result = [lambda x: x + i for i in range(10)]
# 后面的lambada x:x +i 为expression 这是一个普通的lambada表达式那他生成的结果是什么? 一个一个的函数
# 看下面的例子就舒服多了
L = [] for i in range(10):
L.append(lambda x: x + i)

那在我们执行result[0](10),其实就是在执行lambda 10: 10 + i ,但是为什么每个i都是9呢?

2.2、函数内部变量的后期绑定(last binding)

我们在写一个函数的时候,函数内不保存这个变量的值,而是在执行的时候去找这个值在哪里绑定上的。

举个例子来说我们在函数中定引用了一个变量,可以不需要提前定义我们只要在使用前定义就可以了,如下面代码

def func():
print(foo) foo = "hello tim" func()

注:这里有个点稍微提醒下,调用函数时这个函数必须是提前定义好的,这个我们称之为“前向引用”,而函数内部变量可以后期再定义,我们称之为“后期绑定”

因为这个变量不是在lambda内定义的,而是在列表生成式内定义的,我先把列表生成式翻译一下:

def make_list():
L =[]
for i in range(10):
def inner(arg):
return i + arg
L.append(inner)
return L result = make_list()
print(result[2](10))

看上面的代码最后返回的都是一个一个的函数,而这个i的值是在循环的时候赋值的,那我们知道这个i的值不是在,inner(lambda)函数中定义的,而是引用的上层函数的变量,当我们使用inner去调用的时候,这时这个for循环已经结束了,i的值也就变成固定了9

所以每当我们通过函数lambda x: x + i 的时候这个i永远是9

2.3、小作修改

那如果说我不想要这样的结果,我想要i是循环的值怎么办,不要直接引用上层变量,把变量传进来就可以了

result = [lambda x, i=i, : x + i for i in range(10)]
print(result[1](10))

翻译一下

def make_list():
L =[]
for i in range(10):
def inner(arg, i=i):
return i + arg
L.append(inner)
return L result = make_list()
print(result[2](10))

2.4、闭包

简单解释下这个概念,在嵌套函数内,嵌套函数应用上层函数的变量(不是全局变量)称之为闭包,

def func():
x = 1 def inner():
print(x)

当我们执行func的时候就会生成一个闭包,func执行完后里面的变量x不会被回收,因为嵌套函数inner还在使用它,常见的应用场景就是我们的装饰器

Python【知识点】面试小点列表生成式小坑的更多相关文章

  1. python协程函数应用 列表生成式 生成器表达式

    协程函数应用 列表生成式 生成器表达式   一.知识点整理: 1.可迭代的:对象下有_iter_方法的都是可迭代的对象 迭代器:对象._iter_()得到的结果就是迭代器 迭代器的特性: 迭代器._n ...

  2. Python高级特性:Python迭代、生成器、列表生成式

    迭代 给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,这种遍历称为迭代(Iteration). 在java和C语言中,迭代是通过循环list的下标来完成的,Pyth ...

  3. Python学习笔记6(列表生成式)

    1.生成列表 要生成list [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],我们可以用range(1, 11): >>> range(1, 11) [1, 2, 3 ...

  4. Python 入门(十)列表生成式

    生成列表 要生成list [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],我们可以用range(1, 11): >>> range(1, 11) [1, 2, 3, ...

  5. 【Python】学习笔记之列表生成式

    列表生成式 主要用于生成较为复杂的列表 常用用法 >>> [x * x for x in range(5) if x % 3 !=1 ] [0, 4, 9] #返回除以3余数不为1的 ...

  6. 【Python】python内置函数、列表生成式、生成器

    一.内置函数 1 print(all([1,2,3,4]))#判断可迭代的对象里面的值是否都为真 2 print(any([0,1,2,3,4]))#判断可迭代的对象里面的值是否有一个为真 3 pri ...

  7. python学习之模块(pip),列表生成式,模块操作mysql,excel

    python基础 生成式 列表生成式 格式 [表达式 for 表达式 in 迭代对象 (可加判断)] 原: res1 = [] for i in range(1,5): res1.append(i) ...

  8. python学习那点事---列表生成式实现大小写字母相互转换

    题目: 已知列表list=["pYTHON","iS",eASY],要求使用列表生成式实现,生成一个新的列表,要求将大写字母转换为小写字母,小写字母转换为大写字 ...

  9. Python 函数递归-三元表达式-列表生成式-字典生成式-匿名函数-内置函数

    上节课复习: 1. 无参装饰器 def 装饰器名字(func): def wrapper(*args,**kwargs): res = func(*args,**kwargs) return res ...

随机推荐

  1. Android soundpool初探

    内容:本编播客主要讲解一下“即时音效”: 特点:快,短. 在播放这类时间短但是要求反应迅速的的音效,就不能够用不能够使用播放时间较长的音乐播放技术了,而应该采取soundpool技术来播放. soun ...

  2. 609E- Minimum spanning tree for each edge

    Connected undirected weighted graph without self-loops and multiple edges is given. Graph contains n ...

  3. php删除文件夹和其下的内容

    原文地址:http://www.cnblogs.com/xiaochaohuashengmi/archive/2011/05/13/2045158.html <?php function del ...

  4. SQL_sql语言的学习

    关系数据库SQL sql基本功能 SQLde 基本概念 主要知识点 1.外模式包含若干视图和部分基本表 2.模式包含若干基本表 3.内模式包含若干存储文件 4操作对象 基本表:本身独立存在的表,一个关 ...

  5. c# Findwindow sendMessage

    using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServi ...

  6. 从零开始学cookie(个人笔记)——一

    未完待续 参考链接 : cookie (储存在用户本地终端上的数据) 关键词: cookie session HTTP 小文本文件 解释 Cookie 是由 Web 服务器保存在用户浏览器上的小文本文 ...

  7. WinDbg命令三部曲

    WinDbg 命令三部曲:(一)WinDbg 命令手册 WinDbg 命令三部曲:(二)WinDbg SOS 扩展命令手册 WinDbg 命令三部曲:(三)WinDbg SOSEX 扩展命令手册

  8. iOS开发面试题整理

    前言 本文借鉴整理了iOS高级开发常见的面试题,并且分博客一一分析,希望能和大家一起进步学习. 欢迎大家关注我的 Github

  9. Ubuntu环境如何上传项目到GitHub网站?

    http://blog.csdn.net/ajianyingxiaoqinghan/article/details/70544159

  10. C. Smallest Word

    链接 [http://codeforces.com/contest/1043/problem/C] 题意 给你一个只包含a,b的字符串,有一种操作把第1个字符到第i个字符的子串进行反转,问要使最后字符 ...