数组和列表
Python中数组和列表是不同的,我敢断言大多数的pythoneer只知道有列表list,却不知道python也有array数组。列表是一个包含不同数据类型的元素集合,而数组是一个只能含相同数据类型的元素集合。
Python的array
库是一个提供数组操作的模块,它提供了一种用于存储和处理多个相同类型元素的容器。与Python的列表list相比,数组array在存储和操作大量数值型数据时更为高效,因为它在内存中以连续的方式存储数据,占用的内存空间更小。
数组创建
array(typecode [, initializer]) -> array
返回一个新数组,该数组的项受类型代码的限制,并通过可选的初始值设定项值进行初始化,该值必须是列表、字符串或可在适当类型的元素上迭代。
数组表示基本值,其行为与列表非常相似,只是其中存储的对象类型受到约束。类型是在对象创建时使用类型代码指定的,该代码是单个字符。
类型代码 typecode
类型 | C类型 | 最小字节 |
'b' | signed integer | 1 |
'B' | unsigned integer | 1 |
'u' | Unicode character | 2 |
'h' | signed integer | 2 |
'H' | unsigned integer | 2 |
'i' | signed integer | 2 |
'I' | unsigned integer | 2 |
'l' | signed integer | 4 |
'L' | unsigned integer | 4 |
'q' | signed integer | 8 |
'Q' | unsigned integer | 8 |
'f' | floating point | 4 |
'd' | floating point | 8 |
创建数组
import array
arr = array.array('i', [1, 2, 3, 4, 5]) # 创建一个整数类型的数组
arr = array.array('u', 'abcde') # 创建一个字符类型的数组
类型属性
import array
arr = array.array('i', [1, 2, 3, 4, 5])
print(arr.typecode) # 打印数组类型 i
数组切片
与列表用法相同:
>>> arr = array.array('i', [1, 2, 3, 4, 5]) >>> arr[0] 1 >>> arr[2] 3 >>> arr[-1] 5 >>> arr[:3] array('i', [1, 2, 3]) >>> arr[3:] array('i', [4, 5]) >>> arr[:-1] array('i', [1, 2, 3, 4]) >>> arr[::-1] array('i', [5, 4, 3, 2, 1]) >>> arr[1::2] array('i', [2, 4]) >>> arr[0::2] array('i', [1, 3, 5])
类型转换
整数数组可以转换到浮点数数组,反之不行。
>>> arr1 = array.array('i', [1, 2, 3, 4, 5]) >>> arr1 array('i', [1, 2, 3, 4, 5]) >>> arr2 = array.array('f', arr1) >>> arr2 array('f', [1.0, 2.0, 3.0, 4.0, 5.0]) >>> arr3 = array.array('i', arr2) Traceback (most recent call last): File "<pyshell#77>", line 1, in <module> arr3 = array.array('i', arr2) TypeError: 'float' object cannot be interpreted as an integer
数组与列表占用内存的比较
import sys, array arr = array.array('i', [_ for _ in range(1024)]) lst = [_ for _ in range(1024)] print(sys.getsizeof(arr)) # 输出:4176 array对象本身的大小 print(sys.getsizeof(lst)) # 输出:8856 列表list对象本身的大小 # 注意:这些值可能因操作系统或Python解释器的实现和版本而略有不同。
数组方法
append()--将一个新项追加到数组的末尾
buffer_info()--返回给出当前内存信息的信息
byteswap()--字节交换数组的所有项
count()--返回对象的出现次数
extend()--通过从可迭代项中附加多个元素来扩展数组
fromfile()--从文件对象读取项
fromlist()--从列表中追加项
frombytes()--从字符串中追加项
fromunicode()--从unicode字符串中追加项
index()--返回对象第一次出现的索引
insert()--在数组中提供的位置插入一个新项
pop()--移除并返回项(默认为最后一个)
remove()--删除对象的第一个出现项
reverse()--反转数组中项目的顺序
tofile()--将所有项写入文件对象
tolist()--返回转换为普通列表的数组
tobytes()--返回转换为字符串的数组
在举例讲解前先来复习一个列表list的方法,用法相同的(绿色标注)可以省略不学:
append(self, object, /) Append object to the end of the list. clear(self, /) Remove all items from list. copy(self, /) Return a shallow copy of the list. count(self, value, /) Return number of occurrences of value. extend(self, iterable, /) Extend list by appending elements from the iterable. index(self, value, start=0, stop=9223372036854775807, /) Return first index of value. Raises ValueError if the value is not present. insert(self, index, object, /) Insert object before index. pop(self, index=-1, /) Remove and return item at index (default last). Raises IndexError if list is empty or index is out of range. remove(self, value, /) Remove first occurrence of value. Raises ValueError if the value is not present. reverse(self, /) Reverse *IN PLACE*. sort(self, /, *, key=None, reverse=False) Sort the list in ascending order and return None.
用法讲解
buffer_info()
返回当前数组缓冲区的内存信息。
import array arr = array.array('i', [1, 2, 3]) buffer_info = arr.buffer_info() print(buffer_info) # 输出包含内存地址、大小等信息的元组
byteswap()
字节交换数组的所有项,通常用于处理二进制数据的不同字节顺序。
import array arr = array.array('i', [0x12345678]) # 假设这是一个32位整数 arr.byteswap() print(arr) # 输出:[305419896] (0x78563412)
fromfile()
从文件对象中读取项,通常用于从二进制文件中读取数据。
import array with open('data.bin', 'rb') as f: arr = array.array('i') arr.fromfile(f, 3) # 从文件中读取3个整数 print(arr) # 输出:假设文件中有3个整数,则输出这些整数构成的数组
fromlist()
从列表中追加项,创建一个新的数组。
import array list_data = [1, 2, 3, 4, 5] arr = array.array('i', list_data) print(arr) # 输出:array('i', [1, 2, 3, 4, 5])
frombytes()
从字节字符串中追加项,创建一个新的数组。
import array byte_data = b'\x01\x02\x03\x04' arr = array.array('B', byte_data) # 'B' 表示无符号字符 print(arr) # 输出:array('B', [1, 2, 3, 4])
tofile()
将所有项写入文件对象,通常用于将数组数据写入二进制文件。
import array arr = array.array('i', [1, 2, 3]) with open('output.bin', 'wb') as f: arr.tofile(f) # 现在'output.bin'文件包含数组的数据
tolist()
返回转换为普通列表的数组。
import array arr = array.array('i', [1, 2, 3]) list_data = arr.tolist() print(list_data) # 输出:[1, 2, 3]
tobytes()
返回转换为字节字符串的数组。
import array arr = array.array('i', [1, 2, 3]) byte_data = arr.tobytes() print(byte_data) # 输出:b'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00'
用法举例
实例1
import array # 创建一个浮点数类型的array实例 float_array = array.array('f', [1.0, 2.0, 3.0, 4.0, 5.0]) # 打印原始数组 print("Original Array:", float_array) # 计算每个元素的平方 squared_array = array.array('f') for num in float_array: squared_array.append(num ** 2) # 打印平方数组 print("Squared Array:", squared_array) # 计算每个元素的立方 cubed_array = array.array('f') for num in float_array: cubed_array.append(num ** 3) # 打印立方数组 print("Cubed Array:", cubed_array) # 计算平方和立方数组的和 sum_squared = sum(squared_array) sum_cubed = sum(cubed_array) # 打印和 print("Sum of Squared:", sum_squared) print("Sum of Cubed:", sum_cubed)
输出结果:
Original Array: array('f', [1.0, 2.0, 3.0, 4.0, 5.0])
Squared Array: array('f', [1.0, 4.0, 9.0, 16.0, 25.0])
Cubed Array: array('f', [1.0, 8.0, 27.0, 64.0, 125.0])
Sum of Squared: 55.0
Sum of Cubed: 225.0
实例2
import array # 原始字符串 original_string = "Hello, World!" # 将字符串转换为字符数组 # 注意:'u' 类型用于存储 Unicode 字符,但在 Python 3 中,'u' 类型已被废弃 # 我们应该使用 'U' 类型来存储 Unicode 字符(码点),但这通常用于宽字符集 # 在此示例中,我们将使用字节数组 'b' 并通过编码字符串来处理它 # 编码原始字符串为字节 encoded_string = original_string.encode('utf-8') # 创建一个字节类型的array实例 byte_array = array.array('b', encoded_string) # 打印字节数组 print("Byte Array:", byte_array) # 查找特定字节(例如查找 'o' 字符的字节表示) # 注意:这里我们查找的是 'o' 字符的 UTF-8 编码的第一个字节 # 在 ASCII 中,'o' 的编码是 0x6F,但在 UTF-8 编码的字符串中,我们需要找到正确的字节序列 # 对于简单的 ASCII 字符,UTF-8 编码与 ASCII 编码相同 target_byte = ord('o') # 获取 'o' 字符的 ASCII 码点值 target_indices = [i for i, b in enumerate(byte_array) if b == target_byte] print("Indices of 'o':", target_indices) # 替换所有 'o' 字符的字节表示为另一个字符(例如 'x') # 注意:直接替换可能破坏 UTF-8 编码的多字节字符序列 # 因此,这个例子仅适用于单字节字符(ASCII 范围内)的字符串 replacement_byte = ord('x') # 获取 'x' 字符的 ASCII 码点值 for i in target_indices: byte_array[i] = replacement_byte # 将修改后的字节数组转换回字符串 # 注意:如果替换了多字节字符的一部分,解码可能会失败 try: modified_string = byte_array.tobytes().decode('utf-8') print("Modified String:", modified_string) except UnicodeDecodeError: print("Decoding failed due to invalid UTF-8 sequence.") # 注意:在处理包含非ASCII字符的字符串时,应该格外小心, # 因为UTF-8编码可能会使用多个字节来表示一个字符。 # 在这种情况下,直接替换单个字节可能会破坏字符的编码。
输出结果:
Byte Array: array('b', [72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, 33])
Indices of 'o': [4, 8]
Modified String: Hellx, Wxrld!
实例3
import array # 创建一个整数类型的array实例 int_array = array.array('i', [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) # 打印原始数组 print("Original Integer Array:", int_array) # 将数组写入文件 with open('int_array.bin', 'wb') as f: int_array.tofile(f) # 打开文件以读取二进制数据 with open('int_array.bin', 'rb') as f: # 读取整个文件到数组中 # 由于我们知道文件中的数据类型和大小,我们可以使用这些信息来创建数组 # 假设文件中的整数是32位的(即 'i' 表示整数),并且我们不知道有多少个整数 # 我们可以先读取文件的大小,然后除以整数的字节大小来得到整数的数量 file_size = f.seek(0, 2) # 移动到文件末尾以获取文件大小 num_ints = file_size // 4 # 假设整数是32位的(4字节) f.seek(0) # 将文件指针重置回文件开头 # 创建一个空的array实例,用于存储读取的数据 read_array = array.array('i') # 从文件中读取整数数据到数组中 read_array.fromfile(f, num_ints) # 打印从文件中读取的数组 print("Array Read from File:", read_array) # 验证两个数组是否相同 assert int_array == read_array print("The arrays are the same.")
输出结果:
Original Integer Array: array('i', [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
Array Read from File: array('i', [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
The arrays are the same.
完。