NumPy数组的复制的几种实现方法

Written by

in

文章目录
  • 简单赋值或函数传参时,不会复制数组对象或其数据,只是对同一对象的 “重命名” 或 “引用传递”。
  • 视图会创建新的数组对象,但共享原始数组的数据。新数组是原数据的 “窗口”,数据本身未被复制。
  • 深复制会创建原数组及其数据的完整副本,新数组拥有独立的内存空间,与原数组完全解耦。
  • 类型 是否创建新对象 是否共享数据 操作 / 方法 数据修改影响 无复制 否 是 简单赋值、函数传参 原数组与新变量相互影响 视图(浅复制) 是 是 view()、数组切片 数据修改相互影响,形状修改不影响原数组 深复制 是 否 copy() 原数组与新数组完全独立 掌握这三种机制,能让你在处理 NumPy 数组时更精准地控制内存和数据一致性,写出更健壮的代码。 到此这篇关于NumPy 数组的复制的几种实现方法的文章就介绍到这了,更多相关NumPy 数组复制内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客! 您可能感兴趣的文章: NumPy数组复制与视图详解 python numpy数组中的复制知识解析 python numpy数组复制使用实例解析
  • 目录
    • 1  无复制(No Copy at All)
      • 1.1  简单赋值:同一对象的多个名称
      • 1.2  函数调用的引用传递
    • 2  视图 / 浅复制(View or Shallow Copy)
      • 2.1  view()方法创建视图
      • 2.2  视图的 “形状独立,数据共享”
      • 2.3  数组切片返回视图
    • 3  深复制(Deep Copy)
      • 3.1  copy()方法创建深复制
      • 3.2  深复制的数据独立性
      • 3.3  大数组切片的内存优化
    • 4  总结:三种方式对比

      在 NumPy 中操作数组时,理解数据的复制机制是避免逻辑错误和内存浪费的关键。新手常因混淆 “复制” 与 “引用” 而踩坑,本文将系统讲解三种场景:无复制、视图(浅复制)和深复制。

      简单赋值或函数传参时,不会复制数组对象或其数据,只是对同一对象的 “重命名” 或 “引用传递”。

      import numpy as np
      
      # 定义原始数组
      a = np.array([[0, 1, 2, 3],
                    [4, 5, 6, 7],
                    [8, 9, 10, 11]])
      b = a  # 无新对象创建,b是a的“别名”
      print(b is a)  # 输出 True,证明是同一对象
      

      此时修改 b 会直接改变 a,因为它们指向同一块内存。

      Python 中可变对象(如 NumPy 数组)以引用方式传递给函数,函数内的操作会影响原对象。

      视图会创建新的数组对象,但共享原始数组的数据。新数组是原数据的 “窗口”,数据本身未被复制。

      c = a.view()
      print(c is a)        # 输出 False,c是新对象
      print(c.base is a)   # 输出 True,c的底层数据由a持有
      print(c.flags.owndata)  # 输出 False,c不“拥有”自己的数据
      

      视图可以独立修改形状,不影响原数组;但修改数据会同步影响原数组。

      c = c.reshape((2, 6))  # 修改c的形状
      print(a.shape)         # 原数组a形状仍为(3, 4)
      
      c[0, 4] = 1234         # 修改c的数据
      print(a)
      # 输出:
      # array([[   0,    1,    2,    3],
      #        [1234,    5,    6,    7],
      #        [   8,    9,   10,   11]])
      

      对数组切片时,返回的是原数组的视图,而非新数组。

      s = a[:, 1:3]  # 切片得到视图s
      s[:] = 10      # 修改视图的数据(注意是s[:] = 10,不是s = 10)
      print(a)
      # 输出:
      # array([[   0,   10,   10,    3],
      #        [1234,   10,   10,    7],
      #        [   8,   10,   10,   11]])
      

      注意:s[:] = 10 是修改视图数据,而 s = 10 是将 s 重新赋值为新对象,不再关联原数组。

      深复制会创建原数组及其数据的完整副本,新数组拥有独立的内存空间,与原数组完全解耦。

      d = a.copy()
      print(d is a)        # 输出 False,d是新对象
      print(d.base is a)   # 输出 False,d与a无任何共享
      

      修改深复制的数组不会影响原数组。

      d[0, 0] = 9999
      print(a)  # 原数组a不受影响,输出与之前一致
      

      当原始数组很大,且仅需要其一小部分时,对切片进行深复制可释放原始数组的内存。

      a = np.arange(int(1e8))  # 创建超大数组
      b = a[:100].copy()       # 对切片深复制,b拥有独立数据
      del a                    # 可释放a占用的大量内存
      

      如果用 b = a[:100](视图),a 会被 b 引用,即使 del a 也无法释放内存。

      类型 是否创建新对象 是否共享数据 操作 / 方法 数据修改影响
      无复制 简单赋值、函数传参 原数组与新变量相互影响
      视图(浅复制) view()、数组切片 数据修改相互影响,形状修改不影响原数组
      深复制 copy() 原数组与新数组完全独立

      掌握这三种机制,能让你在处理 NumPy 数组时更精准地控制内存和数据一致性,写出更健壮的代码。

      到此这篇关于NumPy 数组的复制的几种实现方法的文章就介绍到这了,更多相关NumPy 数组复制内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!

      您可能感兴趣的文章:

      • NumPy数组复制与视图详解
      • python numpy数组中的复制知识解析
      • python numpy数组复制使用实例解析

      站内搜索