首页 > 解决方案 > 生成具有 x 维的嵌套列表

问题描述

我想创建一个返回具有给定形状的矩阵的函数,类似于np.zeros(shape)在 numpy.

我尝试了以下方法,它有效:

shape = [1,2,3]
x = [ lambda : 0 ]
x.append( lambda : [ x[0]() for _ in range(shape[0])] )
x.append( lambda : [ x[1]() for _ in range(shape[1])] )
x.append( lambda : [ x[2]() for _ in range(shape[2])] )
print(x[-1]())

但是,当我尝试将其自动化以处理如下任意数量的维度时,我得到了 RecursionError。

shape = [1,2,3]
x = [ lambda : 0 ]
for i,s in enumerate(shape): 
    x.append( lambda: [ x[i]() for _ in range(s)] )
print(x[-1]())

有人知道这里出了什么问题,或者是否有更好的方法来做到这一点?

标签: python

解决方案


代码的第二个版本的问题是,当 lambda 被执行时,它们将使用 and 的当前值is这是他们在最后一个循环中获得的值(这里是 2 和 3)。

所以,你在循环中创建的实际上都是

lambda : [ x[2]() for _ in range(3)] 

包括 at x[2],它将在无限递归中调用自己。

经典的“技巧”是利用在定义时评估默认参数的事实。因此,我们使用 lambdas 的默认参数,它将“捕获”每个定义的值i和时间:s

shape = [1, 2, 3]
x = [lambda: 0]
for i,s in enumerate(shape): 
    x.append(lambda i=i, s=s: [ x[i]() for _ in range(s)])

print(x[-1]())

输出:

[[[0], [0]], [[0], [0]], [[0], [0]]]

您还可以使用递归函数构建它,这可能更容易理解:

def nested_list(shape, value):
    if len(shape) == 1:
        return [value] *  shape[0]
    return [nested_list(shape[:-1], value) for _ in range(shape[-1])]


shape = [1,2,3]
print(nested_list(shape, 0))
# [[[0], [0]], [[0], [0]], [[0], [0]]]

推荐阅读