2 回答
TA贡献1827条经验 获得超8个赞
正如Elegant Odoo 的回答所指出的,Python lambdas 通过引用捕获变量。
搜索答案时您可能会听到的另一个术语是“后期绑定”,这意味着只有在执行 lambda 时才会将 lambda 内的变量绑定到它的实际值。结果,您创建的所有 lambda 函数都具有相同的(和最终的)值k,这会导致无限递归。
虽然exec基于 - 的方法是有效的,但我认为大多数人都会同意exec在实际代码中应该避免这种做法。对此的替代解决方案是通过函数创建 lambda 函数以强制早期绑定:
n = 3
func_list = [lambda x: 1]
def create_fn(k_val):
return lambda x: func_list[k_val - 1](x) * (x + k_val)
for k in range(1, n):
func_list.append(create_fn(k))
print(list(map(lambda f: f(1), func_list)))
当您调用create_fnwith 时k, 的当前值将k传递给 name 下的函数k_val。然后k_val将 lambda 函数中的k_val变量绑定到 范围内的变量,并在调用它时create_fn使用 的值。k
TA贡献1844条经验 获得超8个赞
一个很好的案例来解释 Reference 和 Value 之间的区别:
让我解释一下为什么会发生这种情况,以了解发生了什么让我们使用普通函数,以便我们可以调试 K 的值:
n = 3
func_list = [lambda x : 1]
for k in range(1,n):
def f(x):
print('K is: ', k)
return func_list[k-1](x) * (x + k)
func_list.append(f)
# just print will be enough to cause error
print(func_list[2])
输出是:
K is : 2
K is : 2
K is : 2
K is : 2
K is : 2
....
....
....
....
RecursionError: maximum recursion depth exceeded while calling a Python object
您在所有方法中使用相同的变量(对 value 的引用)。K 引用循环生成的值 2。
在循环 make 结束后进行演示k = 5,这将引发错误index out of range。
一个简单的解决方案exec:
n = 3
func_list = [lambda x: 1]
for k in range(1, n):
# here you are not using variable k we are using the value it's like
# we are rewriting it to code every time but is not you who typing it's the compute -_^
exec('func_list.append(lambda x : func_list[{k}-1](x) * (x + {k}))'.format(k=k))
# lambda print(f(1)) will create [None, None, None] I removed the print
print(list(map(lambda f: f(1), func_list)))
输出:
[1, 2, 6]
诅咒上述解决方案适用于您的情况,因为K它只是一个简单Integer 的假设,K它是一个非常复杂的对象,具有复杂的属性和私有变量。为了达到同样的目的,您需要重建对象。
# we need to consract another object using the value
exec('... KClass({}, {}, {}) ...'.format(k.attr1, k.attr2, k.attr2))
KClass使用您的属性 Object 的成像XClass将需要构造两个 object k and x。
所以使用exec工厂模式是不实际的更好的方法来处理这个问题:
n = 3
func_list = [lambda x: 1]
def method_factory(k):
# here K reference it's not the same K reference that is created
# in loop there are different but with the alias K
return lambda x: func_list[k - 1](x) * (x + k)
for k in range(1, n):
func_list.append(method_factory(k))
print(list(map(lambda f: f(1), func_list)))
为什么会这样,因为当您调用method_factory它时,它将创建自己的范围,其中包含一个带有别名的引用,K该引用指向value的引用指向的引用相同。Kloop
希望你明白这一切都是关于reference和的scopes。
添加回答
举报