美文网首页
python 一个实例融合lambda、迭代器、闭包、列表表达式

python 一个实例融合lambda、迭代器、闭包、列表表达式

作者: lzp1234 | 来源:发表于2019-05-16 11:26 被阅读0次

前言

一个有趣的例子,两种写法:

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)

结果:


image.png

在父函数中定义的可变变量会传递给子函数。
在父函数中定义的不可变变量不会传递给子函数。

相关文章

网友评论

      本文标题:python 一个实例融合lambda、迭代器、闭包、列表表达式

      本文链接:https://www.haomeiwen.com/subject/aqjuaqtx.html