为了账号安全,请及时绑定邮箱和手机立即绑定

动态创建 lambda 函数列表,其中每个下一个函数使用前一个函数

动态创建 lambda 函数列表,其中每个下一个函数使用前一个函数

慕姐8265434 2022-05-24 10:12:45
我想创建lambdas一个给定大小n的列表(因此手动分配不起作用),其中每个元素取决于先前的函数并且它在列表中索引。我尝试过各种类似的东西:n = 3func_list = [lambda x : 1]for k in range(1,n):    func_list.append(lambda x : func_list[k-1](x) * (x+k))print(list(map(lambda f : print(f(1)), func_list)))但在所有尝试中,我都收到了关于recursion深度的错误消息:RecursionError                            Traceback (most recent call last)<ipython-input-296-f35123a830c4> in <module>      2 for k in range(1,3):      3     func_list.append(lambda x : func_list[k-1](x) * (x+k))----> 4 print(list(map(lambda f : print(f(1)), func_list)))<ipython-input-296-f35123a830c4> in <lambda>(f)      2 for k in range(1,3):      3     func_list.append(lambda x : func_list[k-1](x) * (x+k))----> 4 print(list(map(lambda f : print(f(1)), func_list)))<ipython-input-296-f35123a830c4> in <lambda>(x)      1 func_list = [lambda x : 1]      2 for k in range(1,3):----> 3     func_list.append(lambda x : func_list[k-1](x) * (x+k))      4 print(list(map(lambda f : print(f(1)), func_list))) ... last 1 frames repeated, from the frame below ...<ipython-input-296-f35123a830c4> in <lambda>(x)      1 func_list = [lambda x : 1]      2 for k in range(1,3):----> 3     func_list.append(lambda x : func_list[k-1](x) * (x+k))      4 print(list(map(lambda f : print(f(1)), func_list)))RecursionError: maximum recursion depth exceeded
查看完整描述

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


查看完整回答
反对 回复 2022-05-24
?
婷婷同学_

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。


查看完整回答
反对 回复 2022-05-24
  • 2 回答
  • 0 关注
  • 112 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信