Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
175 views
in Technique[技术] by (71.8m points)

python - Numpy arrays changing id

What is happening here? It seems like the id locations of the array is not remaining steady maybe?is operator is returning False even thought the ids are same. then after printing the arrays the ids of elements are changing. Any explanations?

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
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

First test with a list:

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

later I tried

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

So the object in a[1] is consistently the integer 1 (id of integers is a bit tricky, and implementation dependent).

But with an array:

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 are totally different; in fact they change with each access:

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

That's because aa[1] isn't just the integer 1. It is a np.int32 object.

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

In contrast to a list, values of an array are stored as bytes in a databuffer. b[1:] is a view and accesses the same data buffer. But a[1] is a new object that contains a reference to that data buffer. In contrast to the list case, a[1] is not the 2nd object in a.

In general, id is not useful when working with arrays, and the is test is also not useful. Use == or isclose (for floats).

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

A way to see where the values of aa are stored is with:

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}

the data pointer for the 2 arrays is related because ba is a view.

aa[1] is array-like, and too has a data buffer, but it isn't a view.

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...