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. docker push images login -u harbor 问题记录 https 证书

    1.[root@dev-100 Desktop]# docker login -u clouder -p engine harbor.xiaowei.com 2.docker tag busybox: ...

  2. php中addslashes(),htmlspecialchars()

    参考转自http://czf2008700.blog.163.com/blog/static/2397283200937103250194/ addslashes -- 使用反斜线引用字符串 stri ...

  3. BZOJ2427: [HAOI2010]软件安装 tarjan+树形背包

    分析: 一开始我以为是裸的树形背包...之后被告知这东西...可能有环...什么!有环! 有环就搞掉就就可以了...tarjan缩点...建图记得建立从i到d[i]之后跑tarjan,因为这样才能判断 ...

  4. Scala--特质

    一.为什么没有多重继承 c++允许多重继承 Java不允许多重继承,类只能继承一个超类,可以实现任意数量的接口. 如何继承这两个抽象基类? Scala提供“特质”而非接口:特质可以同时抽象方法和具体方 ...

  5. 云计算背后的秘密:NoSQL诞生的原因和优缺点

    转载收藏一篇对nosql讲解的比较全面的文章:http://blog.csdn.net/xlgen157387/article/details/47908797 这篇文章将和大家聊聊为什么NoSQL会 ...

  6. SSRS配置2:加密管理

    在初始化Reporting Service时,SSRS会自动创建数据库[ReportServer],用于存储报表元数据,报表订阅,以及凭证(Credential)和连接信息等身份验证信息,身份验证数据 ...

  7. 第一次软件工程作业(One who wants to wear the crown, Bears the crown.)

    回顾你过去将近3年的学习经历 1.当初报考的时候,是真正的喜欢计算机这个专业吗? 报考时对于计算机专业只能说不讨厌,也可以认为对其没有任何的感觉. 有一个比我自己还注意我未来的老妈,我的报考只能通过一 ...

  8. eclipse + maven + com.sun.jersey 创建 restful api

    maven 创建 jersey 项目 如果没找到 jersey archetype, 下载 maven 的 archetype xml, 然后导入 archetypes 运行 右击 main.java ...

  9. HDU排序水题

    1040水题; These days, I am thinking about a question, how can I get a problem as easy as A+B? It is fa ...

  10. CentOS7使用winbind加入AD

    https://ishm.idv.tw/?p=336 CentOS 7 使用 winbind 加入 AD 需求:已經熟悉 CentOS 6 的 AD 加入方式,CentOS 7 已將 winbind ...