如何查找具有相同ID的所有变量?
比方说,我有一个numpy
阵列a
创造b
这样的:如何查找具有相同ID的所有变量?
a = np.arange(3)
b = a
如果我现在改变b
例如这样
b[0] = 100
和打印a
,b
,他们id
S和.flags
print a
print a.flags
print b
print b.flags
print id(a)
print id(b)
我获得
[100 1 2]
C_CONTIGUOUS : True
F_CONTIGUOUS : True
OWNDATA : True
WRITEABLE : True
ALIGNED : True
UPDATEIFCOPY : False
[100 1 2]
C_CONTIGUOUS : True
F_CONTIGUOUS : True
OWNDATA : True
WRITEABLE : True
ALIGNED : True
UPDATEIFCOPY : False
139767698376944
139767698376944
所以,a
和b
看起来相同,它们的id
S皆相等如预期。
当我现在用copy()
c = np.arange(3)
d = c.copy()
d[0] = 20
print c
print c.flags
print id(c)
print d
print d.flags
print id(d)
做同样的我得到
[0 1 2]
C_CONTIGUOUS : True
F_CONTIGUOUS : True
OWNDATA : True
WRITEABLE : True
ALIGNED : True
UPDATEIFCOPY : False
139767698377344
[20 1 2]
C_CONTIGUOUS : True
F_CONTIGUOUS : True
OWNDATA : True
WRITEABLE : True
ALIGNED : True
UPDATEIFCOPY : False
139767698376864
在这种情况下c
和d
不尽相同,因此做他们的id
秒;也如预期。
但是,令我困惑的是我从.flags
获得的输出:在所有情况下,OWNDATA
设置为True
。当我看到documentation,我发现:
OWNDATA(O)的阵列拥有它使用存储器或从 另一个目的借用它。
我的主要问题是现在:
什么是最简单的方法来查找指向同一个id
(以上a
和b
的例子),即所有变量,以检查是否有相同的另一个变量ID是否存在?我认为OWNDATA
会有帮助,但显然不是。
相关问题:
什么实际用于OWNDATA
,在这种情况下是OWNDATA
设置为False
?
有两个问题 - 您如何识别要比较的变量以及如何比较它们。
第一个。
我的版本(1.8.2)没有np.shares_memory
函数。它有一个np.may_share_memory
。
https://github.com/numpy/numpy/pull/6166是添加shares_memory
的拉取请求;它是在去年八月注明的。所以你必须有全新的numpy
来使用它。请注意,确定性测试可能很难,并且可能会作为“太难”错误消息发布。我想,例如有一些片共享内存,但很难通过比较缓冲区起点来识别。
https://github.com/numpy/numpy/blob/97c35365beda55c6dead8c50df785eb857f843f0/numpy/core/tests/test_mem_overlap.py是这些memory_overlap
函数的单元测试。如果您想了解什么是令人畏惧的任务,那么请仔细考虑两个已知阵列之间的所有可能的重叠条件。
我喜欢看阵列的.__array_interface__
。该字典中的一个项目是'数据',它是指向数据缓冲区的指针。相同的指针意味着数据被共享。但一种观点可能会从某个地方开始。如果shares_memeory
查看此指针,我不会感到惊讶。
相同id
表示2个变量引用同一个对象,但不同的数组对象可以共享一个数据缓冲区。
所有这些测试需要寻找特定的参考;所以你仍然需要得到某种引用列表。看看locals()
?, globals()
。那么未命名的引用如数组列表或某些用户定义的字典呢?
一个例子IPython中运行:
一些变量和引用:
In [1]: a=np.arange(10)
In [2]: b=a # reference
In [3]: c=a[:] # view
In [4]: d=a.copy() # copy
In [5]: e=a[2:] # another view
In [6]: ll=[a, a[:], a[3:], a[[1,2,3]]] # list
比较id
:
In [7]: id(a)
Out[7]: 142453472
In [9]: id(b)
Out[9]: 142453472
别人的无共享id
,除了ll[0]
。
In [10]: np.may_share_memory(a,b)
Out[10]: True
In [11]: np.may_share_memory(a,c)
Out[11]: True
In [12]: np.may_share_memory(a,d)
Out[12]: False
In [13]: np.may_share_memory(a,e)
Out[13]: True
In [14]: np.may_share_memory(a,ll[3])
Out[14]: False
这就是我期望的;意见共享内存,副本不。
In [15]: a.__array_interface__
Out[15]:
{'version': 3,
'data': (143173312, False),
'typestr': '<i4',
'descr': [('', '<i4')],
'shape': (10,),
'strides': None}
In [16]: a.__array_interface__['data']
Out[16]: (143173312, False)
In [17]: b.__array_interface__['data']
Out[17]: (143173312, False)
In [18]: c.__array_interface__['data']
Out[18]: (143173312, False)
In [19]: d.__array_interface__['data']
Out[19]: (151258096, False) # copy - diff buffer
In [20]: e.__array_interface__['data']
Out[20]: (143173320, False) # differs by 8 bytes
In [21]: ll[1].__array_interface__['data']
Out[21]: (143173312, False) # same point
只是这短短的会议上,我甲肝在locals()
76项。但我可以搜索它匹配id
与:
In [26]: [(k,v) for k,v in locals().items() if id(v)==id(a)]
Out[26]:
[('a', array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])),
('b', array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))]
其他测试相同。
我可以以同样的方式搜索ll
:
In [28]: [n for n,l in enumerate(ll) if id(l)==id(a)]
Out[28]: [0]
而且我可以,如果一个项目是一个列表或字典,做内搜索的层添加到由测试locals()
搜索。
所以,即使我们解决的测试方法,这是不平凡搜索所有可能的引用。
我认为最好的办法是只了解自己使用的变量,这样就可以清楚地标识引用,看法和副本。在选定的情况下,您可以执行测试,如may_share_memory
或比较数据缓冲区。但是没有一个便宜的,明确的测试。如果有疑问,制作副本会更便宜,而不是冒险写一些东西。在我使用numpy
年的时候,我从来没有觉得需要对这个问题给出明确的答案。
我没有找到OWNDATA
标志非常有用。考虑上述变量
In [35]: a.flags['OWNDATA']
Out[35]: True
In [36]: b.flags['OWNDATA'] # ref
Out[36]: True
In [37]: c.flags['OWNDATA'] # view
Out[37]: False
In [38]: d.flags['OWNDATA'] # copy
Out[38]: True
In [39]: e.flags['OWNDATA'] # view
Out[39]: False
虽然我可以预测在这些简单的情况下,OWNDATA
价值,它的价值不说太多关于共享内存或共享ID。 False
表明它是从另一个数组创建的,因此可能共享内存。但这只是一个'可能'。
我经常创建通过变形的范围内的样品阵列。
In [40]: np.arange(3).flags['OWNDATA']
Out[40]: True
In [41]: np.arange(4).reshape(2,2).flags['OWNDATA']
Out[41]: False
显然没有其他的数据引用,但重构后的数组并不拥有自己的数据。同样的情况也与
temp = np.arange(4); temp = temp.reshape(2,2)
发生,我不得不做
temp = np.arange(4); temp.shape = (2,2)
保持OWNDATA
真。假设OWNDATA
表示创建新数组对象后的情况,但如果原始引用被重新定义或删除,则不会更改。它很容易过时。
作业b=a
不会在原始数组a
上创建视图,而只是创建对其的引用。换句话说,b
只是a
的不同名称。变量a
和b
指的是相同的数组,其拥有其数据,使得OWNDATA
标志被设置。修改b
将修改a
。
作业b=a.copy()
创建原始数组的副本。也就是说,a
和b
指的是单独的数组,它们都拥有它们的数据,以便设置标记OWNDATA
。修改b
将不会修改a
。
但是,如果您分配b=a[:]
,您将创建原始数组的视图,并且b
将不拥有其数据。修改b
将修改a
。
shares_memory
功能就是你要找的。它在框中表示它:检查数组a
和b
是否具有共享内存,从而相互影响。
你似乎对Python中的'='做了些什么不清楚。当你做'b = a'时,你没有两个数组。 [这里有一个快速指南,指出这个语言中'='的意思。](http://nedbatchelder.com/text/names.html) – user2357112
感谢您的参考,但问题仍然存在:如何找到所有具有相同的变量IDS? OWNDATA实际使用的是什么? – Cleb
一次只有一个对象具有给定的ID。 – user2357112