繁体   English   中英

在python中使用lambda表达式在循环内生成函数

[英]Generating functions inside loop with lambda expression in python

如果我列出两个函数列表:

def makeFun(i):
    return lambda: i

a = [makeFun(i) for i in range(10)]
b = [lambda: i for i in range(10)]

为什么列表ab不以保存方式运行?

例如:

>>> a[2]()
2
>>> b[2]()
9

正如其他人所说,范围界定是问题所在。 请注意,您可以通过向 lambda 表达式添加额外参数并为其分配默认值来解决此问题:

>> def makeFun(i): return lambda: i
... 
>>> a = [makeFun(i) for i in range(10)]
>>> b = [lambda: i for i in range(10)]
>>> c = [lambda i=i: i for i in range(10)]  # <-- Observe the use of i=i
>>> a[2](), b[2](), c[2]()
(2, 9, 2)

结果是i现在被明确地放置在仅限于lambda表达式的范围内。

从技术上讲,lambda 表达式在全局作用域中可见的i上是封闭的,最后设置为 9。这与在所有 10 个 lambda 中引用的i相同 例如,

i = 13
print b[3]()

makeFun函数中,lambda 在调用函数时定义的i上关闭。 那是十个不同的i

一组函数 (a) 对传递的参数进行操作,另一组 (b) 对全局变量进行操作,然后将其设置为 9。检查反汇编:

>>> import dis
>>> dis.dis(a[2])
  1           0 LOAD_DEREF               0 (i)
              3 RETURN_VALUE
>>> dis.dis(b[2])
  1           0 LOAD_GLOBAL              0 (i)
              3 RETURN_VALUE
>>>

增加一些清晰度(至少在我看来)

def makeFun(i): return lambda: i
a = [makeFun(i) for i in range(10)]
b = [lambda: i for i in range(10)]

a 使用 makeFun(i),它是一个带参数的函数。

b 使用 lambda: i 这是一个没有参数的函数。 它使用的 i 与之前的非常不同

为了使 a 和 b 相等,我们可以使两个函数不使用参数:

def makeFun(): return lambda: i
a = [makeFun() for i in range(10)]
b = [lambda: i for i in range(10)]

现在这两个函数都使用全局 i

>>> a[2]()
9
>>> b[2]()
9
>>> i=13
>>> a[2]()
13
>>> b[2]()
13

或者(更有用)让两者都使用一个参数:

def makeFun(x): return lambda: x
a = [makeFun(i) for i in range(10)]
b = [lambda x=i: x for i in range(10)]

我故意将 i 更改为 x ,其中变量是本地的。 现在:

>>> a[2]()
2
>>> b[2]()
2

成功 !

python中的Lambdas共享它们创建的变量范围。在你的第一种情况下,lambda的范围是makeFun的。 在第二种情况下,它是全局i ,它是 9 ,因为它是循环的剩余部分。

反正我是这么理解的。。。

不错的收获。 列表推导式中的 lambda 每次都看到相同的本地i

您可以将其重写为:

a = []
for i in range(10):
    a.append(makefun(i))

b = []
for i in range(10):
    b.append(lambda: i)

结果相同。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM