Python【知识点】面试小点列表生成式小坑
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【知识点】面试小点列表生成式小坑的更多相关文章
- python协程函数应用 列表生成式 生成器表达式
协程函数应用 列表生成式 生成器表达式 一.知识点整理: 1.可迭代的:对象下有_iter_方法的都是可迭代的对象 迭代器:对象._iter_()得到的结果就是迭代器 迭代器的特性: 迭代器._n ...
- Python高级特性:Python迭代、生成器、列表生成式
迭代 给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,这种遍历称为迭代(Iteration). 在java和C语言中,迭代是通过循环list的下标来完成的,Pyth ...
- Python学习笔记6(列表生成式)
1.生成列表 要生成list [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],我们可以用range(1, 11): >>> range(1, 11) [1, 2, 3 ...
- Python 入门(十)列表生成式
生成列表 要生成list [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],我们可以用range(1, 11): >>> range(1, 11) [1, 2, 3, ...
- 【Python】学习笔记之列表生成式
列表生成式 主要用于生成较为复杂的列表 常用用法 >>> [x * x for x in range(5) if x % 3 !=1 ] [0, 4, 9] #返回除以3余数不为1的 ...
- 【Python】python内置函数、列表生成式、生成器
一.内置函数 1 print(all([1,2,3,4]))#判断可迭代的对象里面的值是否都为真 2 print(any([0,1,2,3,4]))#判断可迭代的对象里面的值是否有一个为真 3 pri ...
- python学习之模块(pip),列表生成式,模块操作mysql,excel
python基础 生成式 列表生成式 格式 [表达式 for 表达式 in 迭代对象 (可加判断)] 原: res1 = [] for i in range(1,5): res1.append(i) ...
- python学习那点事---列表生成式实现大小写字母相互转换
题目: 已知列表list=["pYTHON","iS",eASY],要求使用列表生成式实现,生成一个新的列表,要求将大写字母转换为小写字母,小写字母转换为大写字 ...
- Python 函数递归-三元表达式-列表生成式-字典生成式-匿名函数-内置函数
上节课复习: 1. 无参装饰器 def 装饰器名字(func): def wrapper(*args,**kwargs): res = func(*args,**kwargs) return res ...
随机推荐
- Ajax的用法
1 Ajax是什么 1.1 Asynchronous JavaScript and XML(异步的javascript和xml) 实质为:使用浏览器内置的一个对象(XmlHttpRequest)向服务 ...
- 卢卡斯定理 Lucas (p为素数)
证明摘自:(我网上唯一看得懂的证明) https://blog.csdn.net/alan_cty/article/details/54318369 结论:(显然递归实现)lucas(n,m)=luc ...
- (四)Lua脚本语言入门(数组遍历)
这篇文章就当成铺垫型的文章,写着写着发现有好多想写的,,关于C#与Java,当然作为铺垫肯定与Lua的下部分介绍有关..... 对于"泛型",先看C#中"泛型" ...
- php操作oracle查询时中文乱码
putenv("LD_LIBRARY_PATH=/usr/lib/oracle/12.1/client64/lib"); putenv("ORACLE_HOME=/usr ...
- 警惕ASP.NET MVC中的ValidateInputAttribute
最近在做一个ASP.NET MVC项目的时候发现,有一个Controller的Action死活都没法接收到从客户端提交过来的Html表单请求和数据,后来才发现是因为默认情况下ASP.NET MVC在执 ...
- ubuntu系统中添加DNS服务器地址后诡异消失的解决办法
今天查看了一下自己电脑里的ubuntu14.04系统,发现无法上网,于是ping了一下百度,出现unknown host,查了一下/etc/resolv.conf中的DNS地址,却发现我之前的修改被清 ...
- bundle install 安装的 gem 提示 cannot load such file
/usr/local/lib/ruby/site_ruby/2.1.0/rubygems/core_ext/kernel_require.rb:54:in `require': cannot load ...
- 20155302 Exp2 后门原理与实践
20155302<网络对抗>后门原理与实践 实验要求 1.使用netcat获取主机操作Shell,cron启动 (0.5分) 2.使用socat获取主机操作Shell, 任务计划启动 (0 ...
- 20155306 白皎 0day漏洞——漏洞利用原理之GS
20155306 白皎 0day漏洞--漏洞利用原理之GS 一.GS安全编译选项的保护原理 1.1 GS的提出 在第二篇博客(栈溢出利用)中,我们可以通过覆盖函数的返回地址来进行攻击,面对这个重灾区, ...
- Python 语言简介
Python是一种计算机程序设计语言.你可能已经听说过很多种流行的编程语言,比如非常难学的C语言,非常流行的Java语言,适合初学者的Basic语言,适合网页编程的JavaScript语言等等. 那P ...