Python中List与Array的区别、转换及高级操作详解

码头散步
码头散步
发布时间:2026-10-14 | 2人浏览过
原创

本文深入解析Python中内置List与NumPy Array的核心区别,涵盖数据类型约束、内存存储机制及性能差异。详细演示了从List到Array的转换方法,包括np.array、np.arange、np.linspace及fromfunction等创建技巧。重点讲解Array的索引访问、布尔索引、列表索引及广播机制,并对比List与Array在拷贝行为上的不同,帮助开发者高效处理数值计算。

List与Array的核心区别

Python中的List是内置的数据类型,其内部元素可以是任意类型,无需保持一致。List存储的是指向数据的指针(即内存地址),而非数据本身。这种设计虽然灵活,但在处理大量数据时,例如list1=[1,2,3,'a'],需要同时维护4个指针和4个数据对象,这会显著增加内存占用和CPU消耗。

相比之下,Num库封装的Array具有更强大的功能,其内部存储的所有元素必须属于相同的数据类型。这种同质性使得Array在数值计算中更加高效。


list1=[1,2,3,'a'] 
print list1 
a=np.array([1,2,3,4,5]) 
b=np.array([[1,2,3],[4,5,6]]) 
c=list(a)  # array到list的转换 
print a,np.shape(a) 
print b,np.shape(b) 
print c,np.shape(c) 

运行结果:


[1, 2, 3, 'a'] # 元素数据类型不同,并且用逗号隔开 
[1 2 3 4 5] (5L,) # 一维数组,类型用tuple表示 
[[1 2 3] 
 [4 5 6]] (2L, 3L) 
[1, 2, 3, 4, 5] (5L,) 

Array的创建与形状操作

创建:

Array的创建可以通过传入List或Tuple作为参数来实现。创建后,可以直接使用shape属性获取数组的形状信息。


a=np.array((1,2,3,4,5))# 参数是元组 
b=np.array([6,7,8,9,0])# 参数是list 
c=np.array([[1,2,3],[4,5,6]])# 参数二维数组 
print a,b, 
c.shape() 

此外,还可以直接修改shape属性来改变数组形状,其中-1表示由系统自动推算。这里并非使用T属性,而是通过reshape((...))方法实现,例如c.shape=4,-1或c.reshape((2,-1))。


c = np.array([[1, 2, 3, 4],[4, 5, 6, 7], [7, 8, 9, 10]]) 
c.shape # (3L, 4L) 
c.shape=4,-1  //c.reshape((2,-1)) 
c  
<pre style="box-sizing: border-box; overflow: auto; font-size: 14px; padding: 0px; margin-top: 0px; margin-bottom: 0px; line-height: 17.0001px; word-break: break-all; word-wrap: break-word; border: 0px; border-radius: 0px; white-space: pre-wrap; vertical-align: baseline; background-color: rgb(255, 255, 255);">array([[ 1, 2, 3], 
    [ 4, 4, 5], 
    [ 6, 7, 7], 
    [ 8, 9, 10]])  

需要注意的是,reshape操作本质上是一个浅拷贝。这意味着修改变换后的数组元素,原始数组的对应数据也会发生变化,因为它们共享相同的内存空间。


d=c.reshape((2,-1)) 
d[1:2]=100 
c 
array([[ 1,  2,  3],
    [ 4,  4,  5],
    [100, 100, 100],
    [100, 100, 100]])

在创建数组时,如果不指定数据类型,默认使用int32。我们也可以显式指定数据类型,例如使用dtype参数设置为np.float64,以控制内存占用和计算精度。


a1=np.array([[1,2,3],[4,5,6]],dtype=np.float64) 
print a1.dtype,a.dtype #float64 int32<pre style="margin-top: 0px; margin-bottom: 0px; line-height: 17.0001px; box-sizing: border-box; overflow: auto; font-size: 14px; padding: 0px; word-break: break-all; word-wrap: break-word; border: 0px; border-radius: 0px; white-space: pre-wrap; vertical-align: baseline; background-color: rgb(255, 255, 255);"> 

NumPy直接创建Array的方法

之前介绍的方法多使用np.array()从Tuple或List转换得到Array,这种方式在处理复杂数据时略显繁琐。NumPy提供了多种直接创建Array的便捷函数,简化了开发流程。


arr1=np.arange(1,10,1) #  
arr2=np.linspace(1,10,10) 
print arr1,arr1.dtype 
print arr2,arr2.dtype 
[1 2 3 4 5 6 7 8 9] int32
[ 1.  2.  3.  4.  5.  6.  7.  8.  9. 10.] float64

np.arange(a,b,c)用于生成从a开始到b结束(不包含b)、步长为c的Array,默认数据类型为int32。而linspace(a,b,c)函数则用于将a到b的范围平均分为c份,结果包含b,适用于生成等差数列。

若需根据坐标为每个元素赋予不同数值,可以使用fromfunction函数。该函数允许通过自定义函数动态生成数组元素。


def fun(i): 
  return i%4+2 
np.fromfunction(fun,(10,)) 
array([ 2., 3., 4., 5., 2., 3., 4., 5., 2., 3.])  

fromfunction函数必须支持多维数组,因此其第二个参数必须是Tuple类型,例如(10,)。若错误地传入(10)这样的整数,会导致报错。


def fun2(i,j): 
  return (i+1)*(j+1) 
np.fromfunction(fun2,(9,9)) 

array([[ 1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9.],
    [ 2.,  4.,  6.,  8., 10., 12., 14., 16., 18.],
    [ 3.,  6.,  9., 12., 15., 18., 21., 24., 27.],
    [ 4.,  8., 12., 16., 20., 24., 28., 32., 36.],
    [ 5., 10., 15., 20., 25., 30., 35., 40., 45.],
    [ 6., 12., 18., 24., 30., 36., 42., 48., 54.],
    [ 7., 14., 21., 28., 35., 42., 49., 56., 63.],
    [ 8., 16., 24., 32., 40., 48., 56., 64., 72.],
    [ 9., 18., 27., 36., 45., 54., 63., 72., 81.]])

尽管NumPy提供了多种直接生成Array的方法,但在实际应用中,大多数情况仍需从List进行转换。这是因为在实际数据处理中,我们通常从txt文件加载数据,读取的数据首先存入List,随后在处理阶段转换为Array。因为Array的设计更符合矩阵运算的需求,涉及矩阵运算时使用mat,而List主要用于元素的简单存取。


def loaddataSet(fileName):  
  file=open(fileName)  
  dataMat=[] // 
  for line in file.readlines():  
    curLine=line.strip().split('\t')  
    floatLine=map(float,curLine)//这里使用的是map函数直接把数据转化成为float类型  
    dataMat.append(floatLine)  
  return dataMat  

上述函数最终返回的是原始的List数据集,根据后续处理需求,可以将其转换为Array或Mat。实际上,Array是Mat的父类,因此凡是可以使用Mat的地方,理论上都可以传入Array。

Array的元素访问与索引机制

元素访问:


arr[5] #5 
arr[3:5] #array([3, 4]) 
arr[:5] #array([0, 1, 2, 3, 4]) 
arr[:-1]# array([0, 1, 2, 3, 4, 5, 6, 7, 8]) 
arr[:] #array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) 
arr[2:4]=100 # array([ 0,  1, 100, 100,  4,  5,  6,  7,  8,  9]) 
arr[1:-1:2] #array([ 1, 100,  5,  7]) 2 是间隔 
arr[::-1] #array([ 9,  8,  7,  6,  5,  4, 100, 100,  1,  0])  
arr[5:2:-1]# -1的间隔表示从右向左所以5>2 #array([ 5,  4, 100]) 

上述示例展示了Array的一维数组访问方式,接下来我们探讨二维数组的处理方法。


print c[1:2]# c[1:2].shape-->(1L, 3L) 
print c[1:2][0] # shape-->(3L,) 
[[4 4 5]]
[4 4 5]
[python] view plain copy 
print c[1] 
print c[1:2] 
[4 4 5]
[[4 4 5]]
[python] view plain copy 
print c[1][2] 
print c[1:4] 
print c[1:4][0][2] 
5
[[ 4  4  5]
 [100 100 100]
 [100 100 100]]
5

可以看出,使用冒号:的表达式最终结果外层仍嵌套一层List的[]。访问Array时必须格外小心,Python语法虽然灵活,索引语法写法正确,但最终结果可能出乎意料。

此外,Array的索引操作最终产生的是原始数据的浅拷贝,修改后的数组与原数组共用一块内存空间。


b=arr[1:6] 
b[:3]=0 
arr #<pre style="box-sizing: border-box; overflow: auto; font-size: 14px; padding: 0px; margin-top: 0px; margin-bottom: 0px; line-height: 17.0001px; word-break: break-all; word-wrap: break-word; border: 0px; border-radius: 0px; white-space: pre-wrap; vertical-align: baseline; background-color: rgb(255, 255, 255);">array([0, 0, 0, 0, 4, 5, 6, 7, 8, 9]) 

产生上述现象的原因是:Array中直接存放数据,拷贝时仅复制指针而未复制实际数据;而List则会发生深拷贝,数据指针全部被带走,互不影响。


list1=list(c) 
list1[1]=0 
list1 #上面修改的0并没有被改变 
[array([1, 2, 3]), 0, array([100, 100, 100]), array([100, 100, 100])]

Array的高级索引与广播机制

除了基本访问外,Array还有更强大的操作方式(仅适用于Array)。

1)使用布尔数组。这种方式非常强大,无需编写复杂的判断语句。注意,这种方式得到的结果不与原始数组共享空间。布尔索引仅适用于Array,List无法使用。布尔索引最终提取下标索引为true的数据,且索引必须是布尔数组。


a=np.array(a*2) 
a>5 
a[a>5] #  
array([16, 32, 48, 64, 80, 16, 32, 48, 64, 80])

2) 列表索引

列表索引可以是Array或List。返回的数据不与原数据共享内存。索引既可以是List也可以是Array。


x=np.arange(10) 
index=[1,2,3,4,5] 
arr_index=np.array(index) 
print x 
print x[index] # list索引 
print x[arr_index] # array索引 
[0 1 2 3 4 5 6 7 8 9]
[1 2 3 4 5]
[1 2 3 4 5]

Array和List区别*2


a=np.arange(10) 
lista=list(a) 
print a*2 
print lista*2 
[ 0 2 4 6 8 10 12 14 16 18]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Array的广播


a = np.arange(0, 60, 10).reshape(-1, 1) 
b = np.arange(0, 5) 
print a 
print b 
[[ 0]
 [10]
 [20]
 [30]
 [40]
 [50]]
[0 1 2 3 4]
print np.add(a,b,c) 
[[ 0 1 2 3 4]
 [10 11 12 13 14]
 [20 21 22 23 24]
 [30 31 32 33 34]
 [40 41 42 43 44]
 [50 51 52 53 54]]

总结

以上所述是小编给大家介绍的python 中的list和array的不同之处及转换问题,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对本站网站的支持!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表