如何调用np.array的值而不是内存地址?

时间:2018-06-18 22:56:53

标签: python arrays numpy

在下面的代码中,我打算从空的列表开始 通过附加(随机)numpy数组。对于临时变量,我初始化了一个numpy数组变量'sample_pt',它作为一个临时变量来保存(随机)numpy数组。虽然我希望有一个随机numpy数组的列表,但输出是一个填充了相同(最终)numpy数组的列表。我怀疑通过其“变量名称”调用numpy数组会返回其内存地址。我是朝着正确的方向前进的,还是有什么值得了解的?

[代码]

import numpy as np

sample_pt=np.array([0.]) # initial point
sample_list=[]
number_iter=3

for _ in range(number_iter):
    sample_pt[0]=np.random.randn()
    sample_list.append(sample_pt)
    print(sample_list)

[输出]

[array([-0.78614157])]
[array([0.7172035]), array([0.7172035])]
[array([0.47565398]), array([0.47565398]), array([0.47565398])]

1 个答案:

答案 0 :(得分:0)

我不知道你的意思是"呼叫值",或者#34;而不是记忆地址",或......你问题的大部分内容。

但问题很简单。您反复追加相同的数组,而不是创建新数组。

如果要创建新阵列,则必须明确地执行此操作。这是微不足道的;只需将np.array构造函数移动到循环中,如下所示:

sample_list=[]
number_iter=3

for _ in range(number_iter):
    sample_pt=np.array([0.]) # initial point
    sample_pt[0]=np.random.randn()
    sample_list.append(sample_pt)
    print(sample_list)

但这可以大大简化。

首先,不是创建一个零的数组然后替换零,为什么不只是创建一个你想要的元素的数组呢?

sample_pt = np.array([np.random.randn()])

或者,更好的是,为什么不让np.random为你构建数组?

sample_pt = np.random.randn(1)

此时你可以用列表理解来替换整个事物:

number_iter = 3
sample_list = [np.random.randn(1) for _ in range(number_iter)]

或者,更好的是,为什么不制作3x1数组而不是3个单元素数组的列表呢?

number_iter = 3
sample_array = np.random.randn((number_iter, 1))

如果由于某种原因确实需要将其更改为3个数组的列表,您可以随时在其上调用list

sample_list = list(sample_array)

......或者一开始就是:

sample_list = list(np.random.randn((number_iter, 1)))

与此同时,我认为你误解了值和变量在Python中是如何工作的。

首先,忘记"内存地址"一秒钟:

  • 对象是一个值,具有类型,位于堆中的某个位置。你不在乎哪里。
  • 变量没有内存地址或类型;它们只是某个命名空间中的名称(全局,本地,某些实例的属性等),它们在某处引用了某些值。

请注意,这与C ++非常不同,C ++中变量是类型化的内存位置,对象存在于这些内存位置。这意味着没有"复制构造函数"或"赋值运算符"或类似Python中的任何内容。当您编写a = b时,这意味着a现在是与b相同值的另一个名称。如果您需要副本,则必须明确要求提供副本。

现在,如果你看看CPython如何在幕后实现的东西:

  • CPython解释器将所有对象表示为PyObject结构的指针,这些结构始终在堆上分配。
  • 变量只是dict中的字符串键,由模块(对于全局变量),实例(对于属性)或其他任何东西拥有。 dict中的值只是与其他任何对象一样的对象。这意味着,在封面下,实际存储在散列表中的是指向键中变量名称的字符串对象的指针,以及指向您在值中分配的任何值的指针。
  • 本地人有一个特殊的优化,包括存储在框架上的一系列对象指针,但你通常不必担心这一点。
  • 还有另一个关闭捕获的特殊技巧,涉及到指向实际对象的指针的单元对象的指针,你不得不担心这些指针。

正如你所看到的,思考这些指针更难理解,并且可能具有误导性,除非你真的关心CPython如何在幕后工作。