前言
一个有趣的例子,两种写法:
b = [lambda x: i*x for i in range(4)]
for j in b:print(j(2))
结果是:
6
6
6
6
a = (lambda x: i*x for i in range(4))
for j in a:print(j(2))
结果是:
0
2
4
6
仅仅是()和[]的区别,结果却大不相同。
本文侧重于解读这两段代码,会简单的介绍lambda、迭代器、闭包、列表表达式,如果毫无基础建议自行搜索学习。
环境
python3.6
基础知识巩固
lambda函数
a = lambda x: x*2
print(a(2))
结果是4
lambda代表定义一个匿名函数,其中 :
左边的 x
代表参数,可用 ,
分割定义多个参数。 :
右边的 x*2
代表返回值
这段lambda可以拆分为:
def test(x):
return x*2
print(test(2))
迭代器
迭代器在python中的类型为generator
通常将迭代器与列表进行比较。列表里存得是具体的值(或内存地址);迭代器并不会直接保存这些值,而是保存过程,动态的生成值。
另:迭代器里的值只能读一次,类似于列表的top操作,它返回一个值后,这个列表就不再包含这个值。
通过一段简单的代码解释:
results = []
for i in range(4):
results.append(1)
这段代码生成一个 包含4个1的数组。你可以反复的遍历这个数组。
但是在迭代器中,保存的不是这些值,而是过程。在迭代器对象上每一次遍历都是执行一次代码,代码执行完,迭代器也就为空了。
后面拆分代码是会写到迭代器,这里有个概念即可。
闭包
通常是指 父方法中有个子方法,但是子方法使用了父方法中的变量。在父方法执行以后并不会立刻释放父方法中的变量,而是将被使用的变量与子方法绑定。
def father(x):
def child():
return x*2
return child()
列表表达式
[x for x in range(4)]
就是在列表中写表达式,此行代码就会生成一个包含0-3的数组
解读
[lambda x: i*x for i in range(4)] 拆分:
def father():
results = []
for i in range(4):
def child(x):
return i*x
results.append(child)
return results
for i in father():
print(i(2))
结果依然是 6 6 6 6。
child函数就是lambda函数。导致这个结果的原因是,child方法中的i 并不是 0 1 2 3,而是最后一次赋值的3。这里需要引入一个例子来解释:
a = 1
def test():
print(a+1)
a = 2
test()
这段代码的结果是3。方法在引用了外部变量时,只有在执行时才会解析变量的值。
回到拆分的代码,在每一次循环时对i重新赋值,但是child方法在执行时才去解析i的值,这就导致了4个child方法中的i变量值都是3。
(lambda x: i*x for i in range(4)) 拆分:
def father():
results = ()
for i in range(4):
def child(x):
return i*x
yield(child)
for i in father():
print(i(2))
结果是 0 2 4 6。
造成这个现象的根本原因就是迭代器。对father这个迭代对象进行遍历时,相当于动态的执行for循环,每次循环输出一次。
总结
原因在于迭代器。
()包裹的列表表达式生成的是迭代器。[]包裹的列表表达式生成的就是普通的数组。
扩展
关于闭包参数传递
子函数可以获取父函数的参数。
但是在父函数中定义的参数,子函数不能随意使用,代码参考:
def found_1(num, group):
is_found = False
def helper():
if num in group:
is_found = True
helper()
return is_found
def found_2(num, group):
is_found = [False]
def helper():
if num in group:
is_found[0] = True
helper()
return is_found[0]
if __name__ == "__main__":
test_num = 1
test_group = [1, 2, 3]
found1 = found_1(test_num, test_group)
found2 = found_2(test_num, test_group)
print(found1)
print(found2)
结果:
![](https://img.haomeiwen.com/i14944275/6ae50842c1ec1d07.png)
在父函数中定义的可变变量会传递给子函数。
在父函数中定义的不可变变量不会传递给子函数。
网友评论