2012-03-05 76 views
1
def make_set(rad): 
    y = [] 
    for i in range(0, rad): 
     x = [] 
     for j in range(0, rad): 
      x.append(0) 
     y.append(x) 
    return y 

def make_set_basic(rad): 
    z = [[0] * rad] * rad 
    return z 

后面的实现(make_set_basic)有什么问题?为什么要用for循环构造多维数组?

回答

6

当使用乘法运算符进行列表时,必须考虑被创建的对象是可变的还是不可变的。

在蟒整数是inmutables,算术运算之后,创建新的对象:

>>> l = [0] * 3 
>>> l 
[0, 0, 0] 
>>> map(id, l) 
[42383312, 42383312, 42383312] 
>>> l[0] += 1 
>>> l 
[1, 0, 0] 
>>> map(id, l) 
[42383288, 42383312, 42383312] 

在上面的例子中,列表中有三个元件他们都指向相同的对象(在此检查使用内建的id)。但是,当第一个元素被修改时,此元素现在指向另一个不同的对象,并且该更改不会影响列表中的其他元素。

在另一方面,如果对象是可变的,当您使用就地修改的对象,你得到的是因为如果修改被应用到列表中的所有对象的方法,结果:

>>> l = [[0]] * 3 
>>> l 
[[0], [0], [0]] 
>>> map(id, l) 
[48544944, 48544944, 48544944] 
>>> l[0].append(0) 
>>> l 
[[0, 0], [0, 0], [0, 0]] 
>>> map(id, l) 
[48544944, 48544944, 48544944] 

请注意,在此示例中,在调用append方法后,没有像上例那样创建新对象。鉴于列表中的所有元素仍然指向同一个对象(内建的id将为它们返回相同的值),将为列表中的所有元素显示对象的新状态。

因此,回答你的问题,因为你可能不想要这种行为,所以你需要在嵌套循环中创建你需要的列表,以确保列表中的所有元素指向一个不同的对象,你可以修改而不改变列表中其他元素的状态作为副作用。

3

它创建rad对同一列表的引用。因为它们是同一个列表,所以在其中一个元素中更改元素会改变它们。

[[0 for x in range(rad)] for y in range(rad)] 
+0

实际上这里只需要一个'for':'[[0] * rad for _ in range(rad)]' – georg 2012-03-05 08:28:56

+0

只因为'0'是不可变的。但它绝不会让人感到痛苦。 – 2012-03-05 08:30:06