我开始使用python,我尝试使用一个二维列表,我开始在每个地方都用相同的变量填充。我想到了这个:

def initialize_twodlist(foo):
    twod_list = []
    new = []
    for i in range (0, 10):
        for j in range (0, 10):
            new.append(foo)
        twod_list.append(new)
        new = []

它给出了预期的结果,但感觉像是一种变通方法。有更简单/更短/更优雅的方法吗?


当前回答

错误方式:[[None*m]*n]

>>> m, n = map(int, raw_input().split())
5 5
>>> x[0][0] = 34
>>> x
[[34, None, None, None, None], [34, None, None, None, None], [34, None, None, None, None], [34, None, None, None, None], [34, None, None, None, None]]
>>> id(x[0][0])
140416461589776
>>> id(x[3][0])
140416461589776

使用这种方法,python不允许为外层列创建不同的地址空间,这将导致各种超出您预期的错误行为。

正确方法,但有例外:

y = [[0 for i in range(m)] for j in range(n)]
>>> id(y[0][0]) == id(y[1][0])
False

这是一个很好的方法,但如果您将默认值设置为None,则会有例外

>>> r = [[None for i in range(5)] for j in range(5)]
>>> r
[[None, None, None, None, None], [None, None, None, None, None], [None, None, None, None, None], [None, None, None, None, None], [None, None, None, None, None]]
>>> id(r[0][0]) == id(r[2][0])
True

因此,使用这种方法正确地设置默认值。

绝对正确的:

跟着麦克风的双循环回复。

其他回答

通常,当你想要多维数组时,你不想要一个列表的列表,而是一个numpy数组,或者可能是一个dict。

例如,使用numpy可以执行如下操作

import numpy
a = numpy.empty((10, 10))
a.fill(foo)
row=5
col=5
[[x]*col for x in [b for b in range(row)]]

上面会给你一个5x5的2D数组

[[0, 0, 0, 0, 0],
 [1, 1, 1, 1, 1],
 [2, 2, 2, 2, 2],
 [3, 3, 3, 3, 3],
 [4, 4, 4, 4, 4]]

它使用嵌套的列表推导式。 分类如下:

[[x]*col for x in [b for b in range(row)]]

[x]*col——>被求值的最终表达式 对于——>中的x, x将是迭代器提供的值 [b for b in range(row)]]——>迭代器。

[b for b in range(row)]]这将计算为[0,1,2,3,4],因为row=5 现在化简为

[[x]*col for x in [0,1,2,3,4]]

它的值是 [[0]*5 for x in[0,1,2,3,4]]——> with x=0第一次迭代 [[1]*5 for x in[0,1,2,3,4]]——> with x=1第二次迭代 [[2]*5 for x in[0,1,2,3,4]]——> with x=2第三次迭代 [[3]*5 for x in[0,1,2,3,4]]——> with x=3第四次迭代 [[4]*5 for x in[0,1,2,3,4]]——> with x=4第五次迭代

如果你使用numpy,你可以很容易地创建2d数组:

import numpy as np

row = 3
col = 5
num = 10
x = np.full((row, col), num)

x

array([[10, 10, 10, 10, 10],
       [10, 10, 10, 10, 10],
       [10, 10, 10, 10, 10]])

代码:

num_rows, num_cols = 4, 2
initial_val = 0
matrix = [[initial_val] * num_cols for _ in range(num_rows)]
print(matrix) 
# [[0, 0], [0, 0], [0, 0], [0, 0]]

Initial_val必须是不可变的。

正如@Arnab和@Mike指出的,数组不是列表。不同之处在于:1)数组在初始化时是固定大小的;2)数组通常支持比列表更少的操作。

也许在大多数情况下有点多余,但这里有一个基本的2d数组实现,它利用python ctypes(c库)实现硬件数组。

import ctypes
class Array:
    def __init__(self,size,foo): #foo is the initial value
        self._size = size
        ArrayType = ctypes.py_object * size
        self._array = ArrayType()
        for i in range(size):
            self._array[i] = foo
    def __getitem__(self,index):
        return self._array[index]
    def __setitem__(self,index,value):
        self._array[index] = value
    def __len__(self):
        return self._size

class TwoDArray:
    def __init__(self,columns,rows,foo):
        self._2dArray = Array(rows,foo)
        for i in range(rows):
            self._2dArray[i] = Array(columns,foo)

    def numRows(self):
        return len(self._2dArray)
    def numCols(self):
        return len((self._2dArray)[0])
    def __getitem__(self,indexTuple):
        row = indexTuple[0]
        col = indexTuple[1]
        assert row >= 0 and row < self.numRows() \
               and col >=0 and col < self.numCols(),\
               "Array script out of range"
        return ((self._2dArray)[row])[col]

if(__name__ == "__main__"):
    twodArray = TwoDArray(4,5,5)#sample input
    print(twodArray[2,3])