diff --git a/doc/source/reference/extensions.rst b/doc/source/reference/extensions.rst index 7b451ed3bf296..e2e8c94ef8fc6 100644 --- a/doc/source/reference/extensions.rst +++ b/doc/source/reference/extensions.rst @@ -60,6 +60,7 @@ objects. api.extensions.ExtensionArray.nbytes api.extensions.ExtensionArray.ndim api.extensions.ExtensionArray.shape + api.extensions.ExtensionArray.tolist Additionally, we have some utility methods for ensuring your object behaves correctly. diff --git a/pandas/core/arrays/base.py b/pandas/core/arrays/base.py index 46b0a6873986e..99c4944a1cfa7 100644 --- a/pandas/core/arrays/base.py +++ b/pandas/core/arrays/base.py @@ -130,6 +130,7 @@ class ExtensionArray: searchsorted shift take + tolist unique view _concat_same_type @@ -1348,6 +1349,22 @@ def _reduce(self, name: str, *, skipna: bool = True, **kwargs): # ------------------------------------------------------------------------ # Non-Optimized Default Methods + def tolist(self) -> list: + """ + Return a list of the values. + + These are each a scalar type, which is a Python scalar + (for str, int, float) or a pandas scalar + (for Timestamp/Timedelta/Interval/Period) + + Returns + ------- + list + """ + if self.ndim > 1: + return [x.tolist() for x in self] + return list(self) + def delete(self: ExtensionArrayT, loc: PositionalIndexer) -> ExtensionArrayT: indexer = np.delete(np.arange(len(self)), loc) return self.take(indexer) diff --git a/pandas/core/arrays/categorical.py b/pandas/core/arrays/categorical.py index c0fc172139149..7e3bf33f411bb 100644 --- a/pandas/core/arrays/categorical.py +++ b/pandas/core/arrays/categorical.py @@ -40,7 +40,6 @@ Ordered, PositionalIndexer2D, PositionalIndexerTuple, - Scalar, ScalarIndexer, SequenceIndexer, Shape, @@ -566,17 +565,11 @@ def itemsize(self) -> int: """ return self.categories.itemsize - def tolist(self) -> list[Scalar]: + def to_list(self): """ - Return a list of the values. - - These are each a scalar type, which is a Python scalar - (for str, int, float) or a pandas scalar - (for Timestamp/Timedelta/Interval/Period) + Alias for tolist. """ - return list(self) - - to_list = tolist + return self.tolist() @classmethod def _from_inferred_categories( diff --git a/pandas/core/base.py b/pandas/core/base.py index 24fa362eea9c3..a1bf448df18c4 100644 --- a/pandas/core/base.py +++ b/pandas/core/base.py @@ -740,9 +740,6 @@ def tolist(self): numpy.ndarray.tolist : Return the array as an a.ndim-levels deep nested list of Python scalars. """ - if not isinstance(self._values, np.ndarray): - # check for ndarray instead of dtype to catch DTA/TDA - return list(self._values) return self._values.tolist() to_list = tolist diff --git a/pandas/tests/extension/base/dim2.py b/pandas/tests/extension/base/dim2.py index b56ec23c63569..b80d2a3586b3b 100644 --- a/pandas/tests/extension/base/dim2.py +++ b/pandas/tests/extension/base/dim2.py @@ -97,6 +97,17 @@ def test_iter_2d(self, data): assert obj.ndim == 1 assert len(obj) == arr2d.shape[1] + def test_tolist_2d(self, data): + arr2d = data.reshape(1, -1) + + result = arr2d.tolist() + expected = [data.tolist()] + + assert isinstance(result, list) + assert all(isinstance(x, list) for x in result) + + assert result == expected + def test_concat_2d(self, data): left = data.reshape(-1, 1) right = left.copy() diff --git a/pandas/tests/extension/base/interface.py b/pandas/tests/extension/base/interface.py index f51f9f732bace..3e8a754c8c527 100644 --- a/pandas/tests/extension/base/interface.py +++ b/pandas/tests/extension/base/interface.py @@ -119,3 +119,9 @@ def test_view(self, data): # check specifically that the `dtype` kwarg is accepted data.view(dtype=None) + + def test_tolist(self, data): + result = data.tolist() + expected = list(data) + assert isinstance(result, list) + assert result == expected