# 2D NumPy array of objects vs. 2D Python list efficiency

**URL:** <https://discuss.python.org/t/2d-numpy-array-of-objects-vs-2d-python-list-efficiency/24663>\
**Category:** Python Help\
**Tags:** help\
**Created:** [March 9, 2023, 10:15pm UTC](https://discuss.python.org/t/2d-numpy-array-of-objects-vs-2d-python-list-efficiency/24663 "2023-03-09T22:15:17Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![pauljurczak](https://avatars.discourse-cdn.com/v4/letter/p/87869e/32.png) [@pauljurczak](https://discuss.python.org/u/pauljurczak)\
**Post date:** [March 9, 2023, 10:15pm UTC](https://discuss.python.org/t/2d-numpy-array-of-objects-vs-2d-python-list-efficiency/24663/1 "2023-03-09T22:15:17Z")

</div>

I have a 2D list `a` of varying shape NumPy arrays and equivalent NumPy array of objects `b = np.array(a, dtype='object')`. It is inconvenient to slice `a`, e.g. `a[:][1]` is not equivalent to `b[:, 1]`, can’t be expressed by slicing and requires a list comprehension `[e[1] for e in a[:]]` instead.

Are there any inefficiencies of using `b` instead of `a`, e.g. copying on construction of `b`? I can’t find references to memory layout and representation details in NumPy documentation, due to “object” being too generic for search engines.

---

<div class="post-metadata">

**Author:** ![franklinvp](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/franklinvp/32/11142_2.png) [@franklinvp](https://discuss.python.org/u/franklinvp)\
**Post date:** [March 10, 2023, 4:54pm UTC](https://discuss.python.org/t/2d-numpy-array-of-objects-vs-2d-python-list-efficiency/24663/2 "2023-03-10T16:54:06Z")

</div>

You can read about the internal representation of `np.array` [here](https://numpy.org/doc/stable/dev/internals.html).

Since you are concerned about efficiency and certain slices, note particularly Point 8 about telling it whether to store your values in row or column major order, the parameter `order` of [the constructor](https://numpy.org/doc/stable/reference/generated/numpy.array.html)

---

<div class="post-metadata">

**Author:** ![kknechtel](https://avatars.discourse-cdn.com/v4/letter/k/e47c2d/32.png) [@kknechtel](https://discuss.python.org/u/kknechtel)\
**Post date:** [March 10, 2023, 11:18pm UTC](https://discuss.python.org/t/2d-numpy-array-of-objects-vs-2d-python-list-efficiency/24663/3 "2023-03-10T23:18:11Z")

</div>

Conceptually, a Numpy array with `dtype=object` will store pointers (of the usual pointer size on the current platform, so normally 64 bits nowadays) that point at the actual underlying Python object representations (i.e., the same sort of pointer as `PyObject *` when writing C code, using the API for working with Python code within C). The same holds if the pointed-at objects are themselves Numpy arrays - since those are still Python objects. A list of lists (not really a “2d list”, but emulating that) will do essentially the same thing, but in multiple levels. A Python list’s underlying memory will store pointers to other Python objects, regardless of the object type, list size or anything else. So the list of lists stores pointers to lists, which store pointers to the “varying shape NumPy arrays”.

Essentially, a Numpy array of objects works similarly to a native Python list, except that

- it keeps track of multiple array dimensions (the array shape), and uses this information to implement more sophisticated indexing;

- it will always represent a rectangular shape (when emulating “2d” with a list of lists, each contained list has its own memory tracking overhead, and can vary in length independently - this is the price for more flexibility);

- it will have a different strategy for reallocating memory when it grows (Numpy arrays are not really meant to be concatenated sequentially).

Aside from that, it’s hard to say anything useful without seeing an actual use case and a specific performance concern.

---

<div class="post-metadata">

**Author:** ![pauljurczak](https://avatars.discourse-cdn.com/v4/letter/p/87869e/32.png) [@pauljurczak](https://discuss.python.org/u/pauljurczak)\
**Post date:** [March 11, 2023, 12:18am UTC](https://discuss.python.org/t/2d-numpy-array-of-objects-vs-2d-python-list-efficiency/24663/4 "2023-03-11T00:18:22Z")

</div>

Thank you for detailed description. So far, my use case is not performance critical. I was mainly looking for more convenient notation and making sure there are no obvious gotchas. My original “2D” list of lists is rectangular and doesn’t require any changes after creation, so it looks like a great fit for Numpy array representation.

---

<div class="post-metadata">

**Author:** ![kknechtel](https://avatars.discourse-cdn.com/v4/letter/k/e47c2d/32.png) [@kknechtel](https://discuss.python.org/u/kknechtel)\
**Post date:** [March 11, 2023, 1:16am UTC](https://discuss.python.org/t/2d-numpy-array-of-objects-vs-2d-python-list-efficiency/24663/5 "2023-03-11T01:16:22Z")

</div>

The next question, of course, is: why don’t the contained Numpy arrays have matching shapes (dimensions)? That would potentially allow for just using a single, higher-dimensional Numpy array, which is much more in-line with how Numpy is intended to work (and how it’s able to deliver performance improvements).

---

<div class="post-metadata">

**Author:** ![pauljurczak](https://avatars.discourse-cdn.com/v4/letter/p/87869e/32.png) [@pauljurczak](https://discuss.python.org/u/pauljurczak)\
**Post date:** [March 11, 2023, 1:42am UTC](https://discuss.python.org/t/2d-numpy-array-of-objects-vs-2d-python-list-efficiency/24663/6 "2023-03-11T01:42:27Z")

</div>

> [@kknechtel](#):
>
> why don’t the contained Numpy arrays have matching shapes

I wish they had, but it’s a non-negotiable nature of a problem at hand.
