4

As my MWE below shows, calling np.array(a, copy=False) on an existing array a returns something that behaves exactly as expected, except that the .data attributes seem to differ. How can this be?

>>> a                               # My original array
array([2])
>>> b = np.array(a, copy=False)     # Not-a-copy of the original array
>>> b is a                          # The Python objects seem to be identical
True
>>> b.data is a.data                # But their .data attributes aren't??
False
>>> a.data
<memory at 0x7f82ebd757c8>
>>> b.data
<memory at 0x7f82ebd75888>
>>> b 
array([2])
>>> a
array([2])
>>> a[:] = 3                        # Changing a indeed also changes b
>>> a
array([3])
>>> b
array([3])
>>> a.data
<memory at 0x7f82ebd757c8>
>>> b.data
<memory at 0x7f82ebd75888>

EDIT

While playing around, I even found that the .data attribute changes while looking at it!

>>> a.data is a.data        # a.data isn't equal to itself?!
False
>>> a.data
<memory at 0x7f82ebd75948>
>>> a.data
<memory at 0x7f82ebd75888>  # A different value than a minute ago
>>> a.data
<memory at 0x7f82ebd75948>
>>> a.data
<memory at 0x7f82ebd75888>
>>> a.data
<memory at 0x7f82ebd75948>
>>> a.data
<memory at 0x7f82ebd75888>
>>> a.data
<memory at 0x7f82ebd75948>
>>> a.data
<memory at 0x7f82ebd75888>
>>> a.data
<memory at 0x7f82ebd75948>
0

2 Answers 2

1
In [33]: a = np.array([2])                                                                             
In [34]: b = np.array(a, copy=False)  

A nice human-readable way of checking for shared data buffer is the __array_interface__ dictionary.

In [36]: a.__array_interface__                                                                         
Out[36]: 
{'data': (69508768, False),
 'strides': None,
 'descr': [('', '<i8')],
 'typestr': '<i8',
 'shape': (1,),
 'version': 3}
In [37]: b.__array_interface__                                                                         
Out[37]: 
{'data': (69508768, False),
 'strides': None,
 'descr': [('', '<i8')],
 'typestr': '<i8',
 'shape': (1,),
 'version': 3}

a.data can be used to make a new array, but otherwise isn't very useful. And even this use is too low-level for most purposes:

In [44]: c = np.ndarray(shape=(1,1), dtype=int, buffer=a.data)                                         
In [45]: c                                                                                             
Out[45]: array([[2]])
In [46]: c.__array_interface__                                                                         
Out[46]: 
{'data': (69508768, False),
 'strides': None,
 'descr': [('', '<i8')],
 'typestr': '<i8',
 'shape': (1, 1),
 'version': 3}
Sign up to request clarification or add additional context in comments.

Comments

0

If you type:

help(a.data)

You will see that it does not return exactly what you expect:

class memoryview(object)
 |  memoryview(object)
 |  
 |  Create a new memoryview object which references the given object.
 |  
 |  Methods defined here:
 |  

It creates a memoryview that references that object. If you want the memory address use id:

id(a) == id(b)
True

Note that:

id(a) is id(b)
False

Because id(a) returns an integer and id(b) too and their memory address isn't the same although their values are.

If you want hexadecimal memory:

hex(id(a))

Also, from NumPy doc: numpy.ndarray.data (I really don't know why this .data is useful but it exists)

7 Comments

I think you are misreading the documentation string. The documentation says that calling the memoryview class creates a new memoryview object. It doesn't say that accessing the data attribute of a numpy array will create a new memoryview object.
Not part of my original question, but the memory address I'm looking for is that of the underlying array, not of the python array objects. The id function doesn't work for this: id(a.view(np.ndarray)) == id(a) returns False.
That's true, haven't thought why it is changing every time but I guess this is because of the python buffer object returned, I will search more about it docs.python.org/3.0/c-api/buffer.html @Martin
You are using view wrong, it should be: id(a.view(type=np.ndarray)) == id(a)` which is Truethe way you wrote the dtype would be np.ndarray and thus would create another array docs.scipy.org/doc/numpy/reference/generated/…
id(a) is not id(b) because two distinct int objects are created. This has nothing to do with the underlying arrays.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.