Python新手在这里。我已经搜索了相当多的解决方案,但没有什么比我需要的更合适。我想在我的程序开头分配一个空数组,它有一行和一列。我提出了一个解决方案,但遇到了一个我没想到的有趣问题。这就是我所拥有的:
a = 7
b = 5
array_ab = [['?'] * b] * a
产生
[['?', '?', '?', '?', '?'],
['?', '?', '?', '?', '?'],
['?', '?', '?', '?', '?'],
['?', '?', '?', '?', '?'],
['?', '?', '?', '?', '?'],
['?', '?', '?', '?', '?'],
['?', '?', '?', '?', '?']]
但是,如果我尝试更改单个元素,它会将每一行视为同一个对象,并有效地将整个列更改为该元素。例如,
array_ab[4][2] = '1'
产生
[['?', '?', '1', '?', '?'],
['?', '?', '1', '?', '?'],
['?', '?', '1', '?', '?'],
['?', '?', '1', '?', '?'],
['?', '?', '1', '?', '?'],
['?', '?', '1', '?', '?'],
['?', '?', '1', '?', '?']]
显然,我需要一种更好的方法来创建空白数组而不是乘法。在python中有解决方案吗? (在FORTRAN中这么简单!)
答案 0 :(得分:5)
的内容
In [12]: a = 5
In [13]: b = 7
In [14]: array_ab = [ [ '?' for i in xrange(a) ] for j in xrange(b) ]
In [15]: array_ab
Out[15]:
[['?', '?', '?', '?', '?'],
['?', '?', '?', '?', '?'],
['?', '?', '?', '?', '?'],
['?', '?', '?', '?', '?'],
['?', '?', '?', '?', '?'],
['?', '?', '?', '?', '?'],
['?', '?', '?', '?', '?']]
In [16]: array_ab[4][2] = '1'
In [17]: array_ab
Out[17]:
[['?', '?', '?', '?', '?'],
['?', '?', '?', '?', '?'],
['?', '?', '?', '?', '?'],
['?', '?', '?', '?', '?'],
['?', '?', '1', '?', '?'],
['?', '?', '?', '?', '?'],
['?', '?', '?', '?', '?']]
特别是,您使用的是list comprehensions和xrange。
答案 1 :(得分:3)
使用list comprehension [['?'] * b for _ in range(a)]
:
In [1405]: a = 7
...: b = 5
...: array_ab = [['?'] * b for _ in range(a)]
In [1406]: array_ab
Out[1406]:
[['?', '?', '?', '?', '?'],
['?', '?', '?', '?', '?'],
['?', '?', '?', '?', '?'],
['?', '?', '?', '?', '?'],
['?', '?', '?', '?', '?'],
['?', '?', '?', '?', '?'],
['?', '?', '?', '?', '?']]
In [1407]: array_ab[4][2] = '1'
In [1408]: array_ab
Out[1408]:
[['?', '?', '?', '?', '?'],
['?', '?', '?', '?', '?'],
['?', '?', '?', '?', '?'],
['?', '?', '?', '?', '?'],
['?', '?', '1', '?', '?'],
['?', '?', '?', '?', '?'],
['?', '?', '?', '?', '?']]
['?']*b
是安全的,因为'?'是一个不可变的字符串,更改字符串列表的元素不会影响其他字符串:
In [1419]: a=['a']*5
In [1420]: a[2]=123
In [1421]: a
Out[1421]: ['a', 'a', 123, 'a', 'a']
虽然[[1,2]]*3
很危险,因为列表可变,这等于:
In [1427]: b=[1,2]
...: a=[b,b,b] #a is just a list of b's references
...: print a
[[1, 2], [1, 2], [1, 2]]
更改内部列表b
的元素不会影响a
的内容。
答案 2 :(得分:3)
如果您打算使用数组进行数值计算,并且可以使用导入外部库,那么我建议您查看numpy
。
它提供了一个数组类和许多有用的数组操作。
创建一个MxN数组就是
import numpy as np
A = np.empty((M,N)) # Empty array
B = np.zeros((M,N)) # Array filled with zeros
然后像
那样完成索引x = A[i,j]
A[4,2] = 1
row1 = A[0, :] # or simply A[0]
答案 3 :(得分:2)
问题在于:
array_ab = [['?'] * 4] * 3
问题是由python选择通过对象引用传递列表这一事实引起的。 因为列表是可变对象。
但是由于列表可能变得非常大,而不是将整个列表转移到内存中,因此Python选择仅使用引用(C语言中的“指针”)。如果将一个变量分配给另一个变量,则只指定对它的引用。这意味着您可以将两个变量指向内存中的相同列表:
>>> a = [1]
>>> b = a
>>> a[0] = 2
>>> print b
[2]
因此,在您的第一行代码中,您有 ['?'] * 4
。
现在['?']
是指向内存中值?
的指针,当您将其相乘时,您会获得指向内存中相同位置的 4
指针。
但是当您更改其中一个值时,Python会知道指针需要更改为指向新值:
>>> a = 4 * ['?']
>>> a
['?', '?', '?', '?']]
您可以验证列表中元素的ID:
>>> [id(v) for v in a]
[33302480, 33302480, 33302480, 33302480]
>>> a[0] = 1
>>> a
[1, '?', '?', '?']
当您将此列表相乘时会出现问题 - 您将获得列表指针的四个副本。 现在,当您更改一个列表中的一个值时,所有四个值都会一起更改。
建议的方法是首先创建所需长度的列表,然后用新创建的列表填充每个元素:
>>> A = [None] * 3
>>> for i in range(3):
... A[i] = [None] * 4
...
>>> A
[[None, None, None, None], [None, None, None, None], [None, None, None, None]]
>>>
这会生成一个包含3个长度为4的不同列表的列表。
或者您可以使用列表理解:
w, h = 4, 3
A = [[None] * w for i in range(h)]
[[None, None, None, None], [None, None, None, None], [None, None, None, None]]
修改2
根据标题,您无法为高级列表分配精确的内存。 Python列表使用某种算法来过度分配列表大小,以便将来进一步增长。
/* This over-allocates proportional to the list size, making room
* for additional growth. The over-allocation is mild, but is
* enough to give linear-time amortized behavior over a long
* sequence of appends() in the presence of a poorly-performing
* system realloc().
* The growth pattern is: 0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ...
*/
答案 4 :(得分:0)
试试这个:
a = 7
b = 5
array_ab = []
for i in range(a):
array_ab.append([])
for j in range(b):
array_ab[i].append('?')
此代码:
array_ab[4][2] = '1'
将array_ab
更改为:
[['?', '?', '?', '?', '?'],
['?', '?', '?', '?', '?'],
['?', '?', '?', '?', '?'],
['?', '?', '?', '?', '?'],
['?', '?', '1', '?', '?'],
['?', '?', '?', '?', '?'],
['?', '?', '?', '?', '?']]