Python高级特性(六)——数组(列表、元组、字节数组)

一、简介

数组是编程语言中的基本数据结构,在很多算法中都有广泛的应用。本文介绍一些Python的数组实现,这些数组只用到了语言的核心特性或Python标准库包含的功能。

另外,会介绍这些实现的优缺点,在合适的场景选择合适的实现方式。在了解这些知识前,需要清楚数组是有大小固定的记录组成,根据索引能找到每个元素, 并且这些元素是存储在连续的内存块中的,所以它是连续的数据结构。

二、实现方式

1、列表——可变动态数组

列表(list)是一种可以添加删除元素的数组实现,还能分配和释放内存来自动调整存储空间,列表中可以包含任意类型的元素,并且可以混合存储。

arr = ['one', 'two', 'three']
print(arr[0])

# 列表的__repr__方法能使列表打印更加直观
print(arr)

# 列表元素可变
arr[0] = 'hello'
print(arr)

# 删除元素
del arr[0]
print(arr)

# 添加不同类型的元素
arr.append(1)
print(arr)

以上代码运行结果:

one
['one', 'two', 'three']
['hello', 'two', 'three']
['two', 'three']
['two', 'three', 1]

关于 python list 的更多用法请点击 此链接

2、元组——不可变容器

元组(tuple)也是Python语言核心的一部分。但与列表不同的是,元组对象是不可变的,不能添加,修改,删除元素,所有元素必须在对象创建时定义。

与列表一样,元素可以包含不同类型的元素,意味着数据的打包密度比固定类型的数组小。

arr = 'one', 'two', 'three'
print(arr[0])

# 元组的__repr__方法同样能使元组打印更加直观
print(arr)

# 元组元素不可变
# arr[0] = 'hello'
# 抛出异常 TypeError: 'tuple' object does not support item assignment

# 元组元素不可删除
# del arr[0]
# 抛出异常 TypeError: 'tuple' object doesn't support item deletion

# 元组元素可以含有任意类型的数据
# 添加元素会产生新元组
arr1 = arr + (1,)
print(arr1)
print(arr.__hash__())
print(arr1.__hash__())

以上代码运行结果

one
('one', 'two', 'three')
('one', 'two', 'three', 1)
-7698655770510080900
1375085398319489189

关于 tuple 的更多使用文档请点击 此链接

3、array.array——基本类型数组

Python array模块用于存储C语言风格的基本数据类型(字节,32位整数,浮点数等),使用该类型创建的数组是可变的,行为与列表相似,但是有一个重要的区别是:这种数组是单一数据类型的“类型数组”, 由于有类型单一的限制,这种数组比元组和列表更加节省存储空间。存储在其中的元素紧密排列,不会有因为元素占用空间不一样导致元素间内存浪费。

arr = array.array('i', (1, 2, 3))
print(arr[0])

# 数组的__repr__方法同样能使数组打印更加直观
print(arr)

# 数组元素可变
arr[1] = 6
print(arr)

# 数组元素可以删除
del arr[1]
print(arr)

# 添加元素
arr.append(10)
print(arr)

# 数组中元素类型是固定的
# arr[1] = 'hello'
# 抛出异常 TypeError: an integer is required (got type str)

以上代码运行结果

1
array('i', [1, 2, 3])
array('i', [1, 6, 3])
array('i', [1, 3])
array('i', [1, 3, 10])

4、含有Unicode字符的不可变数组

Python3.x 使用str对象将文本存储为不可变的Unicode字符序列,这意味着str是不可变的字符数组,str是一种递归数据结构,字符串中的每个元素都是长度为1的str对象

由于字符串对象存储单一数据类型,因为很节省空间,适合用来存储Unicode文本。因为字符串在Python中是不可变的,所有修改字符串需要有一个副本,可以用存储单个字符串的列表来实现这种“可变字符串”。

arr = 'hello'
print(arr[0])

print(arr)

# 字符串是不可变的
# arr[1] = 'e'
# 抛出异常 TypeError: 'str' object does not support item assignment

# 字符串中字符不可删除
# del arr[1]
# 抛出异常 TypeError: 'str' object doesn't support item deletion

# 可以解包到列表中,产生可变版本
str_list = list(arr)
print(str_list)
print(''.join(str_list))

# 字符串是递归数据类型
print(type('abc'))
print(type('abc'[0]))

以上代码运行结果:

h
hello
['h', 'e', 'l', 'l', 'o']
hello
<class 'str'>
<class 'str'>
5、bytes —— 含有单字节的不可变数组

bytes对象是单字节的不可变序列,单字节范围为0~255(含)之间的整数,bytes和str很像,可以认为是不可变的字节数组

bytes同样能通过字面语法进行创建,并且很节省空间。与字符串不一样的是,它有专门的可变字节数组,bytes可以解包到bytearray中。

arr = bytes((1, 2, 3, 4))
print(arr[0])

# 通过字符串加b前缀创建bytes
print(arr)
arr = b'\x01\x02\x03\x04'

# bytes必须是0~255间的整数类型
# bytes((1, 2, 3, 300))
# 抛出异常 ValueError: bytes must be in range(0, 256)

# bytes是不可变的
# arr[1] = 23
# 抛出异常 TypeError: 'bytes' object does not support item assignment

# bytes中的元素不可删除
# del arr[1]
# 抛出异常 TypeError: 'bytes' object doesn't support item deletion

以上代码运行结果

1
b'\x01\x02\x03\x04'
6、bytearray——含有单字节的可变数组

bytearray 类型是可变整数序列,包含的整数范围在0~255。bytearray与bytes关系密切,主要区别在于bytearray可以自由修改,如覆盖、删除先有元素和添加新元素,此时bytearray对象将相应的增长和缩小。

bytearary可以转回不可变的bytes对象,但是这需要复制所存储的数据,是耗时为O(n)的慢操作

arr = bytearray((0, 1, 2, 3))
print(arr[0])

print(arr)

# bytearray是可变的
arr[1] = 23
print(arr)

# bytearray可以增长或缩小
del arr[1]
print(arr)

arr.append(42)
print(arr)

# 只能是0~255间的整数类型
# arr[1] = 'hello'
# 抛出异常 TypeError: 'str' object cannot be interpreted as an integer
# arr[1] = 300
# 抛出异常 ValueError: byte must be in range(0, 256)

# bytearray可以转回bytes数据类型
print(bytes(arr))

以上代码运行结果:

0
bytearray(b'\x00\x01\x02\x03')
bytearray(b'\x00\x17\x02\x03')
bytearray(b'\x00\x02\x03')
bytearray(b'\x00\x02\x03*')
b'\x00\x02\x03*'

三、总结

对于上述几种不同的数组实现,在不同的场景有不同的选择,大致可以按照以下几点去选择对应的实现方式:

  • 如果需要存储任意对象,且其中可能含有混合数据类型,那么可以选择使用列表或元组,前者可变后者不可变。
  • 如果存储数值(整数或浮点数),数据并要求排列紧密且注重性能,那么先尝试array.array,看能否满足需求。另外还可尝试Numpy和Pandas
  • 如果需要用Unicode字符表示的文本数据,可以使用str。如果需要用到“可变字符串”,请使用字符列表
  • 如果想存储连续的字节块,不可变的请使用bytes,可变请使用bytearray。

在大多数情况下优先选择列表实现,在性能或存储空间上有瓶颈,再考虑其他数据类型。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值