Python 玩转数据 6 – NumPy ndarray 数组 和 Python list 列表的区别

引言

前两篇文章有介绍 Python 动态类型 共享引用赋值和拷贝的原理,对 Python list 列表应该有一个深刻的了解。那么 NumPy 中的 ndarray 数组和 list 列表有啥区别呢。更多 Python 进阶系列文章,请参考 Python 进阶学习 玩转数据系列

内容提要:

  1. Python 中不同类型的内存需求
  2. NumPy ndarray Vs. Python list 内存需求
  3. NumPy ndarray Vs. Python list 结构
  4. NumPy ndarray Vs. Python list 计算
  5. NumPy subarray Vs. Python sublist
  6. NumPy ndarray Vs. Python list 总结

Python 中不同类型的内存需求

一个变量被赋值成不同类型的值,它在内存中的存储需求也是不一样的。如下:

from sys import getsizeof as byte_size

x = 5
print("byte size of int_type:{}".format(byte_size(x)))
x = 'hello'
print("byte size of str_type:{}".format(byte_size(x)))
x = True
print("byte size of bool_type:{}".format(byte_size(x)))
x = 5.0
print("byte size of float_type:{}".format(byte_size(x)))

输出:

byte size of int_type:28
byte size of str_type:54
byte size of bool_type:28
byte size of float_type:24

list 中每个元素所占用内存大小取决于每个元素的类型,如下:

from sys import getsizeof as byte_size

list_object = ['Five', 5, 5.0, True]
print("byte size of list_object:{}".format(byte_size(list_object)))
print("byte size of each list item in list_object:{}".format([byte_size(item) for item in list_object]))
print("total byte size of list items in list_object:{}".format(sum([byte_size(item) for item in list_object])))

输出:

byte size of list_object:96
byte size of each list item in list_object:[53, 28, 24, 28]
byte total size of list items in list_object:133

NumPy ndarray Vs. Python list 内存的需求

先通过代码来了解一下:

from sys import getsizeof as byte_size
import numpy as np

list_object = [1,2,3,4,5,6]
np_array = np.array(list_object, dtype='int16')

print("list_object:{}".format(list_object))
print("byte size of list_object:{}".format(byte_size(list_object)))
print("byte size of each list item in list_object:{}".format([byte_size(item) for item in list_object]))
print("total byte size of list items in list_object:{}\n".format(sum([byte_size(item) for item in list_object])))

print("np_array:{}".format(np_array))
print("byte size of each item in np_array:{}".format([item.nbytes for item in np_array]))
print("total byte size of items in np_array:{}".format(np_array.nbytes))

输出:
可见 NumPy array 数组所需内存更少

list_object:[1, 2, 3, 4, 5, 6]
byte size of list_object:112
byte size of each list item in list_object:[28, 28, 28, 28, 28, 28]
total byte size of list items in list_object:168

np_array:[1 2 3 4 5 6]
byte size of each item in np_array:[2, 2, 2, 2, 2, 2]
total byte size of items in np_array:12

NumPy ndarray Vs. Python list 结构:

NumPy ndarray: 存储的是数组里元素的值

一个指向数据(内存或内存映射文件中的一块数据)的指针。
数据类型或 dtype,描述在数组中的固定大小值的格子。
一个表示数组形状(shape)的元组,表示各维度大小的元组。
一个跨度元组(stride),其中的整数指的是为了前进到当前维度下一个元素需要”跨过”的字节数。

Python 玩转数据 6 - NumPy ndarray 数组 和 Python list 列表的区别
Python list: 存储的是 list 元素的引用,即内存地址,不是值
Python 玩转数据 6 - NumPy ndarray 数组 和 Python list 列表的区别

; NumPy ndarray Vs. Python list 计算:

NumPy ndarry 可以进行数据间的算术运算。
Python list 之间不可以直接进行算术运算

import numpy as np

list_object = [1,2,3,4,5,6]
np_array = np.array(list_object, dtype='int16')

list_object_plus= list_object + list_object
np_array_plus = np_array + np_array
np_array_minus = np_array - np_array
np_array_divide = np_array / np_array
np_array_multi = np_array * np_array
print("list_object:{}".format(list_object))
print("list_object + list_object:{}\n".format(list_object_plus))

print("np_array:{}".format(np_array))
print("np_array + np_array:{}".format(np_array_plus))
print("np_array - np_array:{}".format(np_array_minus))
print("np_array * np_array:{}".format(np_array_divide))
print("np_array / np_array:{}".format(np_array_multi))

输出:

list_object:[1, 2, 3, 4, 5, 6]
list_object + list_object:[1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6]

np_array:[1 2 3 4 5 6]
np_array + np_array:[ 2  4  6  8 10 12]
np_array - np_array:[0 0 0 0 0 0]
np_array * np_array:[1. 1. 1. 1. 1. 1.]
np_array / np_array:[ 1  4  9 16 25 36]

NumPy subarray Vs. Python sublist

我们通过例子来看一下 subarray 和 sublist 的不同

import numpy as np

list_object = [1,2,3,4,5,6]
np_array = np.array(list_object, dtype='int16')

list_object_sub = list_object[0:4]
np_array_sub = np_array[0:4]

print("origin list_object:{}".format(list_object))
print("origin np_array:{}".format(np_array))
print("origin list_object_sub:{}".format(list_object_sub))
print("origin np_array_sub:{}".format(np_array_sub))

list_object_sub[0] = 0
np_array_sub[0] = 0

print("after changed list_object_sub:{}".format(list_object_sub))
print("after changed np_array_sub:{}".format(np_array_sub))
print("list_object:{}".format(list_object))
print("np_array:{}".format(np_array))

输出:
可以看出 NumPy subarray 就是一个原 array 的一个视图,它的改变会影响到原 array。而 Python sublist 其实是原 list 的一个浅copy,它的改动不会影响到原list。

origin list_object:[1, 2, 3, 4, 5, 6]
origin np_array:[1 2 3 4 5 6]
origin list_object_sub:[1, 2, 3, 4]
origin np_array_sub:[1 2 3 4]
after changed list_object_sub:[0, 2, 3, 4]
after changed np_array_sub:[0 2 3 4]
list_object:[1, 2, 3, 4, 5, 6]
np_array:[0 2 3 4 5 6]

NumPy ndarray Vs. Python list 总结:

NumPy ArrayPython List创建时size创建 array时,size是固定的,一旦改变size,原来的array会被删除,重新创建一个新的arraylist 的size可以动态变化存储方式连续内存空间不连续内存空间item 内存每个item所占内存一样每个item所占内存可以不一样item 类型每个item 类型必须一致每个item类型可以不一样总体内存内存占用较少内存占用比较多用来支持动太类型矢量计算直接支持大量数学计算不直接支持

Original: https://blog.csdn.net/wumingxiaoyao/article/details/122022596
Author: wumingxiaoyao
Title: Python 玩转数据 6 – NumPy ndarray 数组 和 Python list 列表的区别

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/760275/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球