【问题标题】:Numpy arrays changing idNumpy 数组更改 id
【发布时间】:2017-03-04 23:10:36
【问题描述】:

这里发生了什么?似乎数组的 id 位置可能不稳定?即使 id 相同,is 运算符也会返回 False。然后在打印数组后,元素的 id 会发生变化。有什么解释吗?

import numpy as np
a = np.arange(27)
b = a[1:5]
a[0] is b[1] #False
id(a[0]) #40038736L
id(b[1]) #40038736L
a #prints the array
id(b[1]) #40038712L
id(a[0]) #40038712L
b[0] #1
a[1] #1
id(b[0]) #40038712L
id(a[1]) #40038784L

【问题讨论】:

  • 这可能适用于包含指向对象的指针的列表。但是数组将值存储在数据缓冲区中。 a[2] 是一个引用该缓冲区的新对象,但它的 ida 或数据缓冲区无关。所以id 在处理数组时没有用。
  • stackoverflow.com/questions/3877230/… 的一半重复。我希望我们有一个“拆分副本”功能。

标签: python python-2.7 numpy


【解决方案1】:

使用列表进行第一次测试:

In [1109]: a=[0,1,2,3,4]
In [1112]: b=a[1:3]

In [1113]: id(a[1])
Out[1113]: 139407616
In [1114]: id(b[0])
Out[1114]: 139407616

In [1115]: a[1] is b[0]
Out[1115]: True

后来我试过了

In [1129]: id(1)
Out[1129]: 139407616

所以a[1] 中的对象始终是整数1(整数的id 有点棘手,并且取决于实现)。

但是有一个数组:

In [1118]: aa=np.arange(5)
In [1119]: ba=aa[1:]

In [1121]: aa[1]
Out[1121]: 1
In [1122]: ba[0]
Out[1122]: 1
In [1123]: id(aa[1])
Out[1123]: 2925837264
In [1124]: id(ba[0])
Out[1124]: 2925836912

id 完全不同;事实上,它们会随着每次访问而改变:

In [1125]: id(aa[1])
Out[1125]: 2925837136
In [1126]: id(ba[0])
Out[1126]: 2925835104

这是因为aa[1] 不仅仅是整数1。它是一个np.int32 对象。

In [1127]: type(aa[1])
Out[1127]: numpy.int32

与列表相比,数组的值以字节形式存储在databuffer 中。 b[1:]view 并访问相同的数据缓冲区。但是a[1] 是一个新对象,其中包含对该数据缓冲区的引用。与列表情况相比,a[1] 不是a 中的第二个对象。

一般来说,id 在处理数组时没有用,is 测试也没有用。使用==isclose(用于浮点数)。

=================

查看aa 的值存储位置的方法是:

In [1137]: aa.__array_interface__
Out[1137]: 
{'data': (179274256, False),      # 'id' so to speak of the databuffer
 'descr': [('', '<i4')],
 'shape': (5,),
 'strides': None,
 'typestr': '<i4',
 'version': 3}
In [1138]: ba.__array_interface__
Out[1138]: 
{'data': (179274260, False),    # this is 4 bytes larger
 'descr': [('', '<i4')],
 'shape': (4,),
 'strides': None,
 'typestr': '<i4',
 'version': 3}

两个数组的data 指针是相关的,因为baview

aa[1] 类似于数组,也有数据缓冲区,但不是视图。

In [1139]: aa[1].__array_interface__
Out[1139]: 
{'__ref': array(1),
 'data': (182178952, False),
 ...}

【讨论】:

  • 您是否介意稍微说明一下为什么 id 会随着对 aa[1] 的每次访问而发生变化。每次调用它的 id 时,它是否都会重新收集和创建垃圾?
  • 这不是垃圾回收的问题。 aa[1] 由方法调用产生,aa.__getitem__((1))。它每次都在创建一个新的np.int32 对象。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-23
  • 1970-01-01
  • 2023-03-09
  • 2023-04-11
  • 1970-01-01
相关资源
最近更新 更多