【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】1.2 ndarray解剖课:多维数组的底层实现
1.2 《ndarray解剖课:多维数组的底层实现》
内容介绍
NumPy 的 ndarray
是其核心数据结构,用于高效处理多维数组。在这篇文章中,我们将深入解析 ndarray
的底层实现,探讨其内存结构、维度、数据类型、步长等关键概念,并通过实验验证这些概念的实际应用。
1.2.1 ndarray与Python列表的核心差异
ndarray
和 Python 列表是两种不同的数据结构,它们在内存布局和性能上有显著的差异。下面是 ndarray
和 Python 列表的核心差异对比表:
特性 | ndarray | Python 列表 |
---|---|---|
内存布局 | 连续的内存块(固定大小) | 动态分配的内存(指向对象的指针) |
数据类型 | 统一的数据类型(dtype) | 混合的数据类型(可以包含任意类型的对象) |
访问速度 | 高效的向量化操作 | 较慢的迭代访问 |
修改成本 | 低(视图和副本) | 高(需要重新分配内存) |
支持的运算 | 广泛的数学和科学计算功能 | 有限的列表操作 |
数据对齐 | 自动对齐(通过步长) | 无对齐 |
计算性能 | 高(利用C/C++实现) | 低(纯Python实现) |
文件读写 | 支持 .npy 和 .npz 文件格式 | 不支持二进制文件格式,需要额外的库支持 |
集成性 | 与 Pandas、Scikit-learn 等科学计算库高度集成 | 与标准库高度集成,但与其他科学计算库集成度较低 |
1.2.2 ndarray内存结构3D示意图
为了更好地理解 ndarray
的内存结构,我们绘制一个 3D 示意图,展示 ndarray
如何在内存中存储多维数组。
内存布局示意图(三维数组示例)
内存地址 | 0x1000 | 0x1004 | 0x1008 | 0x100C | 0x1010 | 0x1014 | … |
---|---|---|---|---|---|---|---|
三维索引 | [0,0,0] | [0,0,1] | [0,1,0] | [0,1,1] | [1,0,0] | [1,0,1] | … |
二维展开 | [0,0] | [0,1] | [1,0] | [1,1] | [2,0] | [2,1] | … |
一维展开 | 0 | 1 | 2 | 3 | 4 | 5 | … |
内存布局验证实验
import numpy as np# 创建基础数组
base_arr = np.arange(6, dtype=np.int32)
print(f"原始数组ID: {id(base_arr)}") # 输出原始数组内存地址# 创建视图
view_arr = base_arr[::2] # 步长切片创建视图
print(f"视图数组ID: {id(view_arr)}") # 地址不同但共享数据# 创建副本
copy_arr = base_arr.copy() # 完整内存复制
print(f"副本数组ID: {id(copy_arr)}") # 全新内存地址# 修改视图影响原始数组
view_arr[0] = 100
print("修改视图后的原始数组:", base_arr) # 输出[100 1 2 3 4 5]
1.2.3 维度(shape)、数据类型(dtype)、步长(strides)的关联关系
ndarray
的三个关键属性是 shape
(维度)、dtype
(数据类型)和 strides
(步长)。它们之间的关系如下:
- shape:表示数组的形状,即每个维度的大小。例如,
shape=(3, 3)
表示一个 3x3 的二维数组。 - dtype:表示数组中每个元素的数据类型。例如,
dtype=np.float64
表示数组中的元素是 64 位浮点数。 - strides:表示在内存中从一个元素移动到下一个元素所需的字节数。例如,在一个
shape=(3, 3)
、dtype=np.float64
的数组中,步长strides=(24, 8)
表示从一个行到下一个行需要移动 24 个字节,从一个列到下一个列需要移动 8 个字节。
步长计算公式推导:
对于形状为 ( d 1 , d 2 , . . . , d n ) (d_1,d_2,...,d_n) (d1,d2,...,dn)的数组,第 k k k维步长:
s t r i d e k = ( ∏ i = k + 1 n d i ) × i t e m s i z e stride_k = \left( \prod_{i=k+1}^{n} d_i \right) \times itemsize stridek=(i=k+1∏ndi)×itemsize
示例:三维数组(2,3,4),数据类型int32(4字节)
axis0_stride = 3*4*4 = 48 字节
axis1_stride = 4*4 = 16 字节
axis2_stride = 4 字节
1.2.4 不同初始化方式的内存分配对比(zeros vs empty)
NumPy 提供了多种初始化数组的方法,其中 np.zeros
和 np.empty
是两个常用的方法。我们将通过实验对比它们的内存分配方式。
import numpy as np# 创建一个 3x3 的零数组
zeros_array = np.zeros((3, 3), dtype=np.float64)
print("零数组:")
print(zeros_array)# 创建一个 3x3 的未初始化数组
empty_array = np.empty((3, 3), dtype=np.float64)
print("未初始化数组:")
print(empty_array)# 验证两个数组的内存地址
print("零数组的内存地址:", id(zeros_array))
print("未初始化数组的内存地址:", id(empty_array))# 验证两个数组的相同元素是否共享内存
a = zeros_array[0, 0]
b = empty_array[0, 0]
print("零数组的首元素内存地址:", id(a))
print("未初始化数组的首元素内存地址:", id(b))
注释:
# 导入 NumPy 库,并将其别名为 np
import numpy as np# 创建一个 3x3 的零数组
# np.zeros 是 NumPy 中用于创建全零数组的函数
# 传入数组的形状和数据类型作为参数
zeros_array = np.zeros((3, 3), dtype=np.float64)
print("零数组:") # 打印零数组
print(zeros_array)# 创建一个 3x3 的未初始化数组
# np.empty 是 NumPy 中用于创建未初始化数组的函数
# 传入数组的形状和数据类型作为参数
empty_array = np.empty((3, 3), dtype=np.float64)
print("未初始化数组:") # 打印未初始化数组
print(empty_array)# 验证两个数组的内存地址
# id() 函数用于获取对象的内存地址
print("零数组的内存地址:", id(zeros_array))
print("未初始化数组的内存地址:", id(empty_array))# 验证两个数组的相同元素是否共享内存
# 获取零数组和未初始化数组的首元素
a = zeros_array[0, 0]
b = empty_array[0, 0]
print("零数组的首元素内存地址:", id(a))
print("未初始化数组的首元素内存地址:", id(b))
1.2.5 数组元属性操作实验(shape修改的边界条件)
ndarray
的 shape
属性可以动态修改,但有一些边界条件需要遵守。我们将通过实验验证这些边界条件。
import numpy as np# 创建一个 3x3 的数组
array = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]], dtype=np.float64)
print("原始数组:")
print(array)# 修改数组的形状为 1x9
array.shape = (1, 9)
print("修改后的数组(1x9):")
print(array)# 修改数组的形状为 9x1
array.shape = (9, 1)
print("修改后的数组(9x1):")
print(array)# 尝试修改数组的形状为 4x3
try:array.shape = (4, 3)
except ValueError as e:print("尝试修改形状为 4x3 时的错误:", e)# 尝试修改数组的形状为 3x3x3
try:array.shape = (3, 3, 3)
except ValueError as e:print("尝试修改形状为 3x3x3 时的错误:", e)# 修改数组的形状为 3x3
array.shape = (3, 3)
print("恢复数组形状为 3x3:")
print(array)
注释:
# 导入 NumPy 库,并将其别名为 np
import numpy as np# 创建一个 3x3 的数组
# np.array 是 NumPy 中用于创建数组的函数
# 传入二维列表,每个子列表代表数组的一行,指定数据类型为 64 位浮点数
array = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]], dtype=np.float64)
print("原始数组:") # 打印原始数组
print(array)# 修改数组的形状为 1x9
# .shape 属性用于获取或设置数组的形状
array.shape = (1, 9)
print("修改后的数组(1x9):") # 打印修改后的数组
print(array)# 修改数组的形状为 9x1
array.shape = (9, 1)
print("修改后的数组(9x1):") # 打印修改后的数组
print(array)# 尝试修改数组的形状为 4x3
# 这将导致 ValueError,因为数组的总元素数(9)不等于目标形状的总元素数(12)
try:array.shape = (4, 3)
except ValueError as e:print("尝试修改形状为 4x3 时的错误:", e)# 尝试修改数组的形状为 3x3x3
# 这将导致 ValueError,因为数组的总元素数(9)不等于目标形状的总元素数(27)
try:array.shape = (3, 3, 3)
except ValueError as e:print("尝试修改形状为 3x3x3 时的错误:", e)# 修改数组的形状为 3x3
# 成功修改回原形状
array.shape = (3, 3)
print("恢复数组形状为 3x3:") # 打印恢复后的数组
print(array)
总结
通过这篇文章,我们深入解析了 NumPy 的 ndarray
的底层实现,探讨了其内存结构、维度、数据类型、步长等关键概念,并通过实验验证了这些概念的实际应用。希望这些内容能帮助你更好地理解和使用 NumPy。
参考文献或资料
参考资料名称 | 链接 |
---|---|
NumPy 官方文档 | https://numpy.org/doc/ |
Python 官方文档 | https://docs.python.org/3/ |
NumPy 入门指南 | https://numpy.org/devdocs/user/quickstart.html |
NumPy 源码分析 | https://github.com/numpy/numpy |
NumPy 速查表 | https://www.kaggle.com/learn/overview |
NumPy 实战案例 | https://www.tensorflow.org/tutorials/quickstart/beginner |
NumPy 书籍推荐 | https://www.springer.com/gp/book/9781484242452 |
NumPy 视频教程 | https://www.youtube.com/watch?v=QUT1VHiLmmI |
NumPy 交互式学习 | https://colab.research.google.com/ |
Python 内存管理 | https://docs.python.org/3/c-api/memory.html |
C 语言内存管理 | https://en.wikipedia.org/wiki/C_memory_allocation |
数据结构与算法 | https://www.geeksforgeeks.org/ |
深度学习中的数组操作 | https://pytorch.org/tutorials/beginner/basics/tensorqs_tutorial.html |
科学计算库对比 | https://www.tensorflow.org/compare |
高效计算技术 | https://en.wikipedia.org/wiki/High-performance_computing |
编程社区讨论 | https://stackoverflow.com/questions/tagged/numpy |
希望这篇文章能帮助你在 NumPy 的学习和使用中更进一步。这篇文章包含了详细的原理介绍、代码示例、源码注释以及案例等。希望这对您有帮助。如果有任何问题请随私信或评论告诉我。
相关文章:

【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】1.2 ndarray解剖课:多维数组的底层实现
1.2 《ndarray解剖课:多维数组的底层实现》 内容介绍 NumPy 的 ndarray 是其核心数据结构,用于高效处理多维数组。在这篇文章中,我们将深入解析 ndarray 的底层实现,探讨其内存结构、维度、数据类型、步长等关键概念,…...
冯诺依曼架构和哈佛架构的主要区别?
冯诺依曼架构(Von Neumann Architecture)和哈佛架构(Harvard Architecture)是两种计算机体系结构,它们在存储器组织、指令处理和数据存取等方面有明显的不同。以下是它们的主要区别: 1.存储器结构 冯诺依曼…...

Gurobi基础语法之字典
Python中的字典:dict 我们先来介绍一下Python语法中的 dict 类型, 字典中可以通过任意键值来对数据进行映射,任何无法修改的python对象都可以当作键值来使用,这些无法修改的Python对象包括:整数(比如:1),浮…...

ceph新增节点,OSD设备,标签管理(二)
一、访问客户端集群方式 方式一: 使用cephadm shell交互式配置 [rootceph141 ~]# cephadm shell # 注意,此命令会启动一个新的容器,运行玩后会退出! Inferring fsid c153209c-d8a0-11ef-a0ed-bdb84668ed01 Inferring config /var/lib/ce…...

利用metaGPT多智能体框架实现智能体-2
1.一些帮助理解的概念 智能体 在MetaGPT看来,可以将智能体想象成环境中的数字人,其中 智能体 大语言模型(LLM) 观察 思考 行动 记忆 这个公式概括了智能体的功能本质。为了理解每个组成部分,让我们将其与人类进…...

Hadoop 与 Spark:大数据处理的比较
💖 欢迎来到我的博客! 非常高兴能在这里与您相遇。在这里,您不仅能获得有趣的技术分享,还能感受到轻松愉快的氛围。无论您是编程新手,还是资深开发者,都能在这里找到属于您的知识宝藏,学习和成长…...
Django 日志配置实战指南
日志是 Django 项目中不可或缺的一部分,它帮助我们记录应用程序的运行状态、调试信息、错误信息等。通过合理配置日志,我们可以更好地监控和调试应用程序。本文将详细介绍如何在 Django 项目中实现日志文件分割、日志级别控制以及多环境日志配置,并结合最佳实践和代码示例,…...
传输层协议TCP与UDP:深入解析与对比
传输层协议TCP与UDP:深入解析与对比 目录 传输层协议TCP与UDP:深入解析与对比引言1. 传输层协议概述2. TCP协议详解2.1 TCP的特点2.2 TCP的三次握手与四次挥手三次握手四次挥手 2.3 TCP的流量控制与拥塞控制2.4 TCP的可靠性机制 3. UDP协议详解3.1 UDP的…...
doris:JSON导入数据
本文介绍如何在 Doris 中导入 JSON 格式的数据文件。Doris 支持导入标准 JSON 格式数据,通过配置相关参数,可以灵活地处理不同的 JSON 数据结构,并支持从 JSON 数据中抽取字段、处理嵌套结构等场景。 导入方式 以下导入方式支持 JSON 格式…...
Ubuntu18.04 搭建DHCP服务器
在Ubuntu系统中,DHCP(动态主机配置协议)服务通常由isc-dhcp-server软件包提供。要配置和使用DHCP服务,你可以按照以下步骤操作: 1. 安装DHCP服务器 首先,你需要安装isc-dhcp-server。打开终端并输入以下命…...

Spring Boot 邂逅Netty:构建高性能网络应用的奇妙之旅
一、引言 在当今数字化时代,构建高效、可靠的网络应用是开发者面临的重要挑战。Spring Boot 作为一款强大的 Java 开发框架,以其快速开发、简洁配置和丰富的生态支持,深受广大开发者喜爱。而 Netty 作为高性能、异步的网络通信框架ÿ…...

【云安全】云原生-Docker(五)容器逃逸之漏洞利用
漏洞利用逃逸 通过漏洞利用实现逃逸,主要分为以下两种方式: 1、操作系统层面的内核漏洞 这是利用宿主机操作系统内核中的安全漏洞,直接突破容器的隔离机制,获得宿主机的权限。 攻击原理:容器本质上是通过 Linux 的…...

九、CSS工程化方案
一、PostCSS介绍 二、PostCSS插件的使用 项目安装 - npm install postcss-cli 全局安装 - npm install postcss-cli -g postcss-cli地址:GitHub - postcss/postcss-cli: CLI for postcss postcss地址:GitHub - postcss/postcss: Transforming styles…...

gradle创建springboot单项目和多模块项目
文章目录 gradle创建springboot项目gradle多模块项目创建 gradle创建springboot项目 适用IDEA很简单,如下图 gradle多模块项目创建 首选创建父项目,然后删除无用内容至下图 选择父项目目录,右键选择模块,创建子项目(…...
Vue实现div滚动,并且支持top动态滚动
如果你知道距离目标 div 顶部的像素值,并希望通过传入 top 参数来实现滚动到对应区域,可以使用 window.scrollTo 方法。 编写滚动方法 const scrollToDiv (targetDiv, top) > {if (targetDiv) {top top * targetDiv.value.scrollHeight / data.he…...

Elasticsearch 中,分片(Shards)数量上限?副本的数量?
概念 ElasticSearch高可用集群架构实战 分片数量1 在 Elasticsearch 中,分片(Shards)是数据存储和索引的基本单位。创建分片时需要考虑多个因素,包括集群的配置、硬件资源(如磁盘空间、内存等)以及性能要…...

Unity入门1
安装之后无法获得许可证,可以考虑重装 新建项目 单击空白处生成脚本 双击c#文件 会自动打开vstudio 检查引用 如果没有引用,重开vstu,或者重新加载项目 hierarchy层级 scenes场景 assets资产 inspector督察 icon图标 资源链接&…...
网络模型简介:OSI七层模型与TCP/IP模型
计算机网络是现代信息社会的基石,而网络通信的基础在于理解网络模型。网络模型是对通信过程的抽象,它帮助我们理解数据从源到目的地的传输过程。常见的网络模型有 OSI 七层模型 和 TCP/IP 模型,这两种模型在理论和实践中都起着重要作用。 一、…...

软件测试压力太大了怎么办?
本文其实是知乎上针对一个问题的回答: 目前在做软件测试,主要负责的是手机端的项目测试,项目迭代很快,每次上线前验正式都会发现一些之前验测试包时候没有发现的问题,压力太大了,应该怎么调整 看过我之前其…...

微信小程序-点餐(美食屋)02开发实践
目录 概要 整体架构流程 (一)用户注册与登录 (二)菜品浏览与点餐 (三)订单管理 (四)后台管理 部分代码展示 1.index.wxml 2.list.wxml 3.checkout.wxml 4.detail.wxml 小结优点 概要…...

利用最小二乘法找圆心和半径
#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...
Java编程之桥接模式
定义 桥接模式(Bridge Pattern)属于结构型设计模式,它的核心意图是将抽象部分与实现部分分离,使它们可以独立地变化。这种模式通过组合关系来替代继承关系,从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...

java高级——高阶函数、如何定义一个函数式接口类似stream流的filter
java高级——高阶函数、stream流 前情提要文章介绍一、函数伊始1.1 合格的函数1.2 有形的函数2. 函数对象2.1 函数对象——行为参数化2.2 函数对象——延迟执行 二、 函数编程语法1. 函数对象表现形式1.1 Lambda表达式1.2 方法引用(Math::max) 2 函数接口…...

车载诊断架构 --- ZEVonUDS(J1979-3)简介第一篇
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 做到欲望极简,了解自己的真实欲望,不受外在潮流的影响,不盲从,不跟风。把自己的精力全部用在自己。一是去掉多余,凡事找规律,基础是诚信;二是…...
CppCon 2015 学习:Reactive Stream Processing in Industrial IoT using DDS and Rx
“Reactive Stream Processing in Industrial IoT using DDS and Rx” 是指在工业物联网(IIoT)场景中,结合 DDS(Data Distribution Service) 和 Rx(Reactive Extensions) 技术,实现 …...

运动控制--BLDC电机
一、电机的分类 按照供电电源 1.直流电机 1.1 有刷直流电机(BDC) 通过电刷与换向器实现电流方向切换,典型应用于电动工具、玩具等 1.2 无刷直流电机(BLDC) 电子换向替代机械电刷,具有高可靠性,常用于无人机、高端家电…...

Redis专题-实战篇一-基于Session和Redis实现登录业务
GitHub项目地址:https://github.com/whltaoin/redisLearningProject_hm-dianping 基于Session实现登录业务功能提交版本码:e34399f 基于Redis实现登录业务提交版本码:60bf740 一、导入黑马点评后端项目 项目架构图 1. 前期阶段2. 后续阶段导…...

2025年上海市“星光计划”第十一届职业院校技能大赛 网络安全赛项技能操作模块样题
2025年上海市“星光计划”第十一届职业院校技能大赛 网络安全赛项技能操作模块样题 (二)模块 A:安全事件响应、网络安全数据取证、应用安全、系统安全任务一:漏洞扫描与利用:任务二:Windows 操作系统渗透测试 :任务三&…...

window安装docker\docker-compose
安装前配置 打开控制面板,参照下图打开“启动或关闭windows功能”,Hyper-V 和容器需要启用 程序和功能 启动或关闭windows功能 勾选Hyper-V 安装路径配置 Docker在Windows上的默认安装路径为C:\Program Files\Docker。 以管理员身份运行CMD在D盘,dev文件夹下创建Docker文…...

模拟搭建私网访问外网、外网访问服务器服务的实践操作
目录 实验环境 实践要求 一、准备工作 1、准备四台虚拟机,分别标号 2、 防火墙额外添加两块网卡,自定义网络连接模式 3、 关闭虚拟机的图形管理工具 4、关闭防火墙 5、分别配置四台虚拟机的IP地址,此处举一个例子(使用的临…...