我是靠谱客的博主 光亮白云,这篇文章主要介绍Python中闭包与lambda的作用域解析,现在分享给大家,希望可以做个参考。

本篇文章给大家带来了关于Python的相关知识,其中主要整理了关于lambda的作用域的相关问题,还有Python中闭包的相关内容,下面一起来看一下,希望对大家有帮助。

【相关推荐:Python3视频教程 】

Python闭包与lambda的作用域

lambda写法

复制代码
1
2
3
4
5
6
def fun(): for i in range(3): yield lambda x : x * i f0, f1, f2 = fun() print(f0(1), f1(2), f2(3))
登录后复制

闭包的写法

复制代码
1
2
3
4
5
6
7
8
9
def fun(): result = [] for i in range(3): def demo(x): return x * i result.append(demo) return result f0, f1, f2 = fun() print(f0(1), f1(2), f2(3))
登录后复制

上面两种写法的结果都是2,4,6,按最初的想法结果应该是0,2,6。

问题原因:

问题的本事在python的变量查找规则,LEGB(local,enclousing,global,bulitin),上面的例子中,i就是在闭包作用域(enclousing),而Python的闭包是迟绑定,闭包中用到的变量i的值,是在内部函数被调用时查找到的。

解决办法

将闭包作用域变为局部作用域

lambda写法

复制代码
1
2
3
4
5
6
def fun(): for i in range(3): yield lambda x, i = i: x * i f0, f1, f2 = fun() print(f0(1), f1(2), f2(3))
登录后复制

闭包写法

复制代码
1
2
3
4
5
6
7
8
9
def fun(): result = [] for i in range(3): def demo(x, i=i): return x * i result.append(demo) return result f0, f1, f2 = fun() print(f0(1), f1(2), f2(3))
登录后复制

以上输出结果0,2,6

另一种情况:

复制代码
1
2
3
4
5
def fun(): for i in range(3): yield lambda x : x * i f0, f1, f2 = fun() print(f0(1), f1(2), f2(3))
登录后复制

输出结果还是2,4,6

问题原因

fun()方法返回的生成器(或迭代器),并没有真正的执行,而是在每次调用的时候进行执行。

在遍历后执行打印时,i这个变量使用的是最后调用的值。将lambda看作闭包方法的话,变量i值还是闭包作用域(no local)

python当中的坑(闭包与lambda)

先来看一个栗子

复制代码
1
2
3
4
5
def create(): return [lambda x:i*x for i in range(5)] for i in create(): print(i(2))
登录后复制

结果:

create函数的返回值时一个列表,列表的每一个元素都是一个函数 -- 将输入参数x乘以一个倍数i的函数。预期的结果时0,2,4,6,8. 但结果是5个8,意外不意外。

由于出现这个陷阱的时候经常使用了lambda,所以可能会认为是lambda的问题,但lambda表示不愿意背这个锅。问题的本质在与python中的属性查找规则,LEGB(local,enclousing,global,bulitin),在上面的例子中,i就是在闭包作用域(enclousing),而Python的闭包是 迟绑定 , 这意味着闭包中用到的变量的值,是在内部函数被调用时查询得到的

解决办法也很简单,那就是变闭包作用域为局部作用域。

复制代码
1
2
3
4
5
def create(): return [lambda x, i=i:i*x for i in range(5)] for i in create(): print(i(2))
登录后复制

换种写法:

复制代码
1
2
3
4
5
6
7
8
9
10
def create(): a = [] for i in range(5): def demo(x, i=i): return x*i a.append(demo) return a for i in create(): print(i(2))
登录后复制

以上两种写法是一样的

结果:

再来一个问题相似的栗子

代码很简单:(声明:python3问题)

复制代码
1
2
3
4
nums = range(2,20) for i in nums: nums = filter(lambda x: x==i or x%i, nums) print(list(nums))
登录后复制

结果:

同样按照正常的逻辑结果应该为:

问题产生的原因:

  • 在python3当中filter()函数返回的是一个迭代器,因此并没有做真正的执行,而是在每次调用的时候执行(python2中filter()返回的值列表,无此现象)
  • 在遍历后执行打印时,现在执行循环当中的函数,同上面一个栗子的问题,i这个变量使用的是最后调用时的值,与以上栗子不同的是以上栗子用的是内嵌作用域的值,而这个栗子用的是全局i的值

修改代码:

复制代码
1
2
3
4
nums = range(2,20) for i in nums: nums = filter(lambda x,i=i: x==i or x%i, nums) print(list(nums))
登录后复制

结果:

【相关推荐:Python3视频教程 】

以上就是Python中闭包与lambda的作用域解析的详细内容,更多请关注靠谱客其它相关文章!

最后

以上就是光亮白云最近收集整理的关于Python中闭包与lambda的作用域解析的全部内容,更多相关Python中闭包与lambda内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(90)

评论列表共有 0 条评论

立即
投稿
返回
顶部