为什么将列表初始化为空而不是预先确定大小是python式的呢?

为什么将列表初始化为空而不是预先确定大小是python式的呢?,python,arrays,list,optimization,Python,Arrays,List,Optimization,我的问题的简短版本:为什么在Python中经常初始化空列表,即使列表的大小可能会更改很多次,例如: arr = [] for i in range(10): arr.append(i) 迭代更改数组的大小在计算上不是很昂贵吗? 我的问题的长篇版本:我习惯于使用MATLAB,并且对Python比较陌生。当我想要创建一个数组时,在MATLAB中,通常的做法是初始化一个大小合适的零数组,然后用你想要的元素替换数组中的元素。这是因为在MATLAB中迭代更改数组的大小在计算上非常昂贵。Python

我的问题的简短版本:为什么在Python中经常初始化空列表,即使列表的大小可能会更改很多次,例如:

arr = []
for i in range(10):
   arr.append(i)
迭代更改数组的大小在计算上不是很昂贵吗?


我的问题的长篇版本:我习惯于使用MATLAB,并且对Python比较陌生。当我想要创建一个数组时,在MATLAB中,通常的做法是初始化一个大小合适的零数组,然后用你想要的元素替换数组中的元素。这是因为在MATLAB中迭代更改数组的大小在计算上非常昂贵。Python有没有什么东西可以避免这种开销?当我看到人们在这个网站上回答Python问题时,涉及到预先初始化要添加到的列表,他们总是创建一个空列表,然后更改大小,我一直认为这是低效的。

创建一个列表并在以后填充它的主要原因是,您不知道有多少元素将进入其中。由于列表本身会动态调整大小,而数组本身就不会调整大小,因为它们通常保留在连续的内存块中,而列表也不必这样,所以以这样一种方式编写代码很方便,可以利用这一事实

但是,上面所述并不是创建列表的好方法。您可能希望使用a来生成以下内容:

arr = [i for i in range(10)]

如果您知道列表中有多少元素,那么您可能希望填充该列表。如果您不知道,则无法填充列表。

创建列表并稍后填充它的要点是,您不知道有多少元素将进入其中。由于列表本身会动态调整大小,而数组本身就不会调整大小,因为它们通常保留在连续的内存块中,而列表也不必这样,所以以这样一种方式编写代码很方便,可以利用这一事实

但是,上面所述并不是创建列表的好方法。您可能希望使用a来生成以下内容:

arr = [i for i in range(10)]

如果您知道列表中有多少元素,那么您可能希望填充该列表。如果您不知道,则无法填充列表。

Python不会逐个增加列表。它总是分配大块。区块大小取决于列表的大小。因此,当列表变大时,预先分配的空间会变大

例如,如果您添加1000万个附件,它将执行大约100个分配,即增加列表的步骤

如果您从一个空列表开始,并通过一次添加一个元素来增加它,那么您将得到以下步骤:实际分配新内存:

 list size:  allocations
        10:   3
       100:  10
      1000:  27
     10000:  46
    100000:  65
   1000000:  85
  10000000: 104

MATLAB阵列与NumPy阵列更具可比性。这些数组的大小是固定的,一步一步地增加它们是非常昂贵的。

Python不会逐个增加列表。它总是分配大块。区块大小取决于列表的大小。因此,当列表变大时,预先分配的空间会变大

例如,如果您添加1000万个附件,它将执行大约100个分配,即增加列表的步骤

如果您从一个空列表开始,并通过一次添加一个元素来增加它,那么您将得到以下步骤:实际分配新内存:

 list size:  allocations
        10:   3
       100:  10
      1000:  27
     10000:  46
    100000:  65
   1000000:  85
  10000000: 104

MATLAB阵列与NumPy阵列更具可比性。这些阵列的大小是固定的,逐步增加它们非常昂贵。

这不是阵列,而是列表。列表的工作原理不同于数组。为了避免开销,
list
s被设计成随着大小的增加而以更大的步长增长(因此
realloc
s随着元素数量的增加而减少),并且它们只存储指向其内容的指针,因此当
realloc
必须移动分配时,它实际上只是一个
memcpy
8*numelements
字节;它的成本有点高,但Python解释器的开销通常掩盖了这样的小成本。@furas:这是正确的(或者至少只有在Python上下文中才正确,因为它扭曲了通常的术语)。出于某种未知的原因,Python将术语“列表”添加到其他语言所称的“数组”或“向量”中。然后numpy拿走了未使用的术语“array”并偷走了它自己。它不是array,而是list。列表的工作原理不同于数组。为了避免开销,
list
s被设计成随着大小的增加而以更大的步长增长(因此
realloc
s随着元素数量的增加而减少),并且它们只存储指向其内容的指针,因此当
realloc
必须移动分配时,它实际上只是一个
memcpy
8*numelements
字节;它的成本有点高,但Python解释器的开销通常掩盖了这样的小成本。@furas:这是正确的(或者至少只有在Python上下文中才正确,因为它扭曲了通常的术语)。出于某种未知的原因,Python将术语“列表”添加到其他语言所称的“数组”或“向量”中。然后numpy拿走了未使用的术语“array”并将其偷走。这很好。您有关于这些数字的任何来源吗?使用pympler自动生成。:)@Cᴏʟᴅsᴘᴇᴇᴅ 这很好。您有关于这些数字的任何来源吗?使用pympler自动生成。:)@Cᴏʟᴅsᴘᴇᴇᴅ