当前位置: 首页 > news >正文

【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】1.2 ndarray解剖课:多维数组的底层实现

在这里插入图片描述

1.2 《ndarray解剖课:多维数组的底层实现》

内容介绍

NumPy 的 ndarray 是其核心数据结构,用于高效处理多维数组。在这篇文章中,我们将深入解析 ndarray 的底层实现,探讨其内存结构、维度、数据类型、步长等关键概念,并通过实验验证这些概念的实际应用。

1.2.1 ndarray与Python列表的核心差异

ndarray 和 Python 列表是两种不同的数据结构,它们在内存布局和性能上有显著的差异。下面是 ndarray 和 Python 列表的核心差异对比表:

特性ndarrayPython 列表
内存布局连续的内存块(固定大小)动态分配的内存(指向对象的指针)
数据类型统一的数据类型(dtype)混合的数据类型(可以包含任意类型的对象)
访问速度高效的向量化操作较慢的迭代访问
修改成本低(视图和副本)高(需要重新分配内存)
支持的运算广泛的数学和科学计算功能有限的列表操作
数据对齐自动对齐(通过步长)无对齐
计算性能高(利用C/C++实现)低(纯Python实现)
文件读写支持 .npy 和 .npz 文件格式不支持二进制文件格式,需要额外的库支持
集成性与 Pandas、Scikit-learn 等科学计算库高度集成与标准库高度集成,但与其他科学计算库集成度较低
1.2.2 ndarray内存结构3D示意图

为了更好地理解 ndarray 的内存结构,我们绘制一个 3D 示意图,展示 ndarray 如何在内存中存储多维数组。

元数据
内存块
3, 3
维度 (shape)
8 (64-bit float)
数据类型 (dtype)
(24, 8)
步长 (strides)
元素1
数据
元素2
元素3
元素4
元素5
元素6
元素7
元素8
元素9
NumPy ndarray
内存块
元数据

内存布局示意图(三维数组示例)

内存地址0x10000x10040x10080x100C0x10100x1014
三维索引[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]
一维展开012345

内存布局验证实验

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+1ndi)×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.zerosnp.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修改的边界条件)

ndarrayshape 属性可以动态修改,但有一些边界条件需要遵守。我们将通过实验验证这些边界条件。

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 的底层实现,探讨其内存结构、维度、数据类型、步长等关键概念&#xff0c…...

冯诺依曼架构和哈佛架构的主要区别?

冯诺依曼架构(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 作为高性能、异步的网络通信框架&#xff…...

【云安全】云原生-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多模块项目创建 首选创建父项目,然后删除无用内容至下图 选择父项目目录,右键选择模块,创建子项目&#xff08…...

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 小结优点 概要…...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻

在如今就业市场竞争日益激烈的背景下,越来越多的求职者将目光投向了日本及中日双语岗位。但是,一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧?面对生疏的日语交流环境,即便提前恶补了…...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练

前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1):从基础到实战的深度解析-CSDN博客,但实际面试中,企业更关注候选人对复杂场景的应对能力(如多设备并发扫描、低功耗与高发现率的平衡)和前沿技术的…...

MMaDA: Multimodal Large Diffusion Language Models

CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构&#xf…...

Device Mapper 机制

Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...

Fabric V2.5 通用溯源系统——增加图片上传与下载功能

fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...

Java + Spring Boot + Mybatis 实现批量插入

在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法&#xff1a;使用 MyBatis 的 <foreach> 标签和批处理模式&#xff08;ExecutorType.BATCH&#xff09;。 方法一&#xff1a;使用 XML 的 <foreach> 标签&#xff…...

免费PDF转图片工具

免费PDF转图片工具 一款简单易用的PDF转图片工具&#xff0c;可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件&#xff0c;也不需要在线上传文件&#xff0c;保护您的隐私。 工具截图 主要特点 &#x1f680; 快速转换&#xff1a;本地转换&#xff0c;无需等待上…...

华为OD机考-机房布局

import java.util.*;public class DemoTest5 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseSystem.out.println(solve(in.nextLine()));}}priv…...

GitHub 趋势日报 (2025年06月06日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...

「全栈技术解析」推客小程序系统开发:从架构设计到裂变增长的完整解决方案

在移动互联网营销竞争白热化的当下&#xff0c;推客小程序系统凭借其裂变传播、精准营销等特性&#xff0c;成为企业抢占市场的利器。本文将深度解析推客小程序系统开发的核心技术与实现路径&#xff0c;助力开发者打造具有市场竞争力的营销工具。​ 一、系统核心功能架构&…...