gpt4 book ai didi

python - 关于 numpy 数组在 Python 中如何存储的一些困惑

转载 作者:行者123 更新时间:2023-11-28 16:20:10 25 4
gpt4 key购买 nike

在 Python 中使用数据类型 numpy 数组时,我有些困惑。

问题一

我在 python 解释器中执行以下脚本

>>> import numpy as np
>>> L = [1000,2000,3000]
>>> A = np.array(L)
>>> B = A

然后我检查以下内容:

>>> A is B
True
>>> id(A) == id(B)
True
>>> id(A[0]) == id(B[0])
True

没关系。但随后发生了一些奇怪的事情。

>>> A[0] is B[0]
False

但是 A[0] 和 B[0] 怎么可能是不同的东西呢?他们有相同的ID!对于 Python 中的列表,我们有

>>> LL = [1000,2000,3000]
>>> SS = LL
>>> LL[0] is SS[0]
True

numpy数组的存储方式和list完全不同?我们还有

>>> A[0] = 1001
>>> B[0]
1001

看来A[0]和B[0]是同一个对象。

问题2

我复制了一份 A。

>>> C = A[:]
>>> C is A
False
>>> C[0] is A[0]
False

没关系。 A 和 C 似乎彼此独立。但是

>>> A[0] = 1002
>>> C[0]
1002

A和C好像不是独立的?我完全糊涂了。

最佳答案

你问的是两个完全独立的问题,所以这里有两个答案。

  1. Numpy 数组的数据在内部存储为连续的 C 数组。数组中的每个条目只是一个数字。另一方面,Python 对象需要一些内务处理数据,例如引用计数和指向类型对象的指针。您不能简单地将原始指针指向内存中的数字。出于这个原因,如果您访问单个元素,Numpy 会在 Python 对象中“装箱”一个数字。每次访问元素时都会发生这种情况,因此即使 A[0]A[0] 也是不同的对象:

    >>> A[0] is A[0]
    False

    这就是为什么 Numpy 可以以更节省内存的方式存储数组的核心:它不会为每个条目存储完整的 Python 对象,并且只在需要时动态创建这些对象。它针对数组的矢量化操作进行了优化,而不是针对单个元素访问进行了优化。

  2. 当您执行 C = A[:] 时,您正在为相同的数据创建一个新 View 。你不是在复制。然后您将有两个不同的包装器对象,分别由 AC 指向,但它们由相同的缓冲区支持。数组的 base 属性指的是最初创建它的数组对象:

    >>> A.base is None
    True
    >>> C.base is A
    True

    与索引结合使用时,相同数据的新 View 特别有用,因为您可以获得仅包含原始数组的某些切片但由相同内存支持的 View 。

    要真正复制数组,请使用 copy() 方法。

作为更笼统的评论,您不应该过多地了解 Python 中的对象标识。通常,如果 x is y 为真,您就知道它们实际上是同一个对象。但是,如果返回 false,它们仍然可以是同一对象的两个不同代理。

关于python - 关于 numpy 数组在 Python 中如何存储的一些困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40911491/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com