Python中List与Array的区别、转换及高级操作详解
本文深入解析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的不同之处及转换问题,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对本站网站的支持!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









