Repository: pandas-dev/pandas
Pull request: ENH: to_list as alias for tolist
- [x] closes #8826
- [x] tests added / passed
- [x] passes `git diff upstream/master -u -- "*.py" | flake8 --diff`
- [x] whatsnew entry


Problem statement:
ENH: Add Series.to_list, alias for tolist
Hello,

IPython autocomplete (tab) shows

```
In [1]: ts.to
ts.to_clipboard  ts.to_frame      ts.to_period     ts.to_string
ts.to_csv        ts.to_hdf        ts.to_pickle     ts.to_timestamp
ts.to_dense      ts.to_json       ts.to_sparse     ts.tolist
ts.to_dict       ts.to_msgpack    ts.to_sql
```

maybe `tolist` should be named `to_list`
and `tolist` should be marked as deprecated
because it seems that other methods follow
an implicit naming convention (`to_...`) . 

Kind regards

Hints from issue discussion:
this is for compat with numpy, e.g. `numpy.tolist` is the standard method.

So, could add `to_list` to call `tolist` but can't change it.

But it would make things a bit more consistent. needs to be added in `pandas/core/base/IndexOpsMixin` (so both series/index getit)

pull-requests welcome!

+1 for adding a `to_list` alias (but indeed not deprecating `tolist`)

Commit message: Fixing Import Order

Patch to review:
diff --git a/doc/source/api.rst b/doc/source/api.rst
index 49c89a53e7b17..9586483d44bdf 100644
--- a/doc/source/api.rst
+++ b/doc/source/api.rst
@@ -323,7 +323,7 @@ Conversion
    Series.bool
    Series.to_period
    Series.to_timestamp
-   Series.tolist
+   Series.to_list
    Series.get_values
 
 
@@ -1534,7 +1534,7 @@ Conversion
    Index.item
    Index.map
    Index.ravel
-   Index.tolist
+   Index.to_list
    Index.to_native_types
    Index.to_series
    Index.to_frame
diff --git a/doc/source/timedeltas.rst b/doc/source/timedeltas.rst
index b32603cb78795..8c4928cd8165e 100644
--- a/doc/source/timedeltas.rst
+++ b/doc/source/timedeltas.rst
@@ -436,11 +436,11 @@ Finally, the combination of ``TimedeltaIndex`` with ``DatetimeIndex`` allow cert
 .. ipython:: python
 
    tdi = pd.TimedeltaIndex(['1 days', pd.NaT, '2 days'])
-   tdi.tolist()
+   tdi.to_list()
    dti = pd.date_range('20130101', periods=3)
-   dti.tolist()
-   (dti + tdi).tolist()
-   (dti - tdi).tolist()
+   dti.to_list()
+   (dti + tdi).to_list()
+   (dti - tdi).to_list()
 
 Conversions
 ~~~~~~~~~~~
@@ -461,7 +461,7 @@ Scalars type ops work as well. These can potentially return a *different* type o
 
    # subtraction of a date and a timedelta -> datelike
    # note that trying to subtract a date from a Timedelta will raise an exception
-   (pd.Timestamp('20130101') - tdi).tolist()
+   (pd.Timestamp('20130101') - tdi).to_list()
 
    # timedelta + timedelta -> timedelta
    tdi + pd.Timedelta('10 days')
diff --git a/doc/source/timeseries.rst b/doc/source/timeseries.rst
index 0d6fc735f3025..2a6249bef112b 100644
--- a/doc/source/timeseries.rst
+++ b/doc/source/timeseries.rst
@@ -2338,7 +2338,7 @@ Infer the ambiguous times
 .. ipython:: python
 
    rng_hourly_eastern = rng_hourly.tz_localize('US/Eastern', ambiguous='infer')
-   rng_hourly_eastern.tolist()
+   rng_hourly_eastern.to_list()
 
 In addition to 'infer', there are several other arguments supported.  Passing
 an array-like of bools or 0s/1s where True represents a DST hour and False a
@@ -2351,8 +2351,8 @@ constructor as well as ``tz_localize``.
 .. ipython:: python
 
    rng_hourly_dst = np.array([1, 1, 0, 0, 0])
-   rng_hourly.tz_localize('US/Eastern', ambiguous=rng_hourly_dst).tolist()
-   rng_hourly.tz_localize('US/Eastern', ambiguous='NaT').tolist()
+   rng_hourly.tz_localize('US/Eastern', ambiguous=rng_hourly_dst).to_list()
+   rng_hourly.tz_localize('US/Eastern', ambiguous='NaT').to_list()
 
    didx = pd.DatetimeIndex(start='2014-08-01 09:00', freq='H',
                            periods=10, tz='US/Eastern')
diff --git a/doc/source/whatsnew/v0.24.0.rst b/doc/source/whatsnew/v0.24.0.rst
index a18c26f911f1d..f01d4edfbf92d 100644
--- a/doc/source/whatsnew/v0.24.0.rst
+++ b/doc/source/whatsnew/v0.24.0.rst
@@ -1071,6 +1071,7 @@ Other API Changes
 - :meth:`Index.hasnans` and :meth:`Series.hasnans` now always return a python boolean. Previously, a python or a numpy boolean could be returned, depending on circumstances (:issue:`23294`).
 - The order of the arguments of :func:`DataFrame.to_html` and :func:`DataFrame.to_string` is rearranged to be consistent with each other. (:issue:`23614`)
 - :meth:`CategoricalIndex.reindex` now raises a ``ValueError`` if the target index is non-unique and not equal to the current index. It previously only raised if the target index was not of a categorical dtype (:issue:`23963`).
+- :func:`Series.tolist` and :func:`Index.tolist()` now have an alias ``to_list`` (:issue:`8826`)
 
 .. _whatsnew_0240.deprecations:
 
diff --git a/pandas/core/arrays/categorical.py b/pandas/core/arrays/categorical.py
index abadd64b441b4..54929845c4b30 100644
--- a/pandas/core/arrays/categorical.py
+++ b/pandas/core/arrays/categorical.py
@@ -309,7 +309,8 @@ class Categorical(ExtensionArray, PandasObject):
     # ops, which raise
     __array_priority__ = 1000
     _dtype = CategoricalDtype(ordered=False)
-    _deprecations = frozenset(['labels'])
+    # tolist is not actually deprecated, just suppressed in the __dir__
+    _deprecations = frozenset(['labels', 'tolist'])
     _typ = 'categorical'
 
     def __init__(self, values, categories=None, ordered=None, dtype=None,
@@ -567,6 +568,8 @@ def tolist(self):
         """
         return list(self)
 
+    to_list = tolist
+
     @property
     def base(self):
         """
diff --git a/pandas/core/base.py b/pandas/core/base.py
index 1d2a0a2544dbc..47ba56eefc8e7 100644
--- a/pandas/core/base.py
+++ b/pandas/core/base.py
@@ -1025,6 +1025,8 @@ def tolist(self):
         else:
             return self._values.tolist()
 
+    to_list = tolist
+
     def __iter__(self):
         """
         Return an iterator of the values.
diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py
index fc5f6758f9e06..3d037af26b954 100644
--- a/pandas/core/indexes/base.py
+++ b/pandas/core/indexes/base.py
@@ -31,7 +31,7 @@
 from pandas.core.dtypes.missing import array_equivalent, isna
 
 from pandas.core import ops
-from pandas.core.accessor import CachedAccessor
+from pandas.core.accessor import CachedAccessor, DirNamesMixin
 import pandas.core.algorithms as algos
 from pandas.core.arrays import ExtensionArray
 from pandas.core.base import IndexOpsMixin, PandasObject
@@ -202,6 +202,9 @@ class Index(IndexOpsMixin, PandasObject):
     >>> pd.Index(list('abc'))
     Index(['a', 'b', 'c'], dtype='object')
     """
+    # tolist is not actually deprecated, just suppressed in the __dir__
+    _deprecations = DirNamesMixin._deprecations | frozenset(['tolist'])
+
     # To hand over control to subclasses
     _join_precedence = 1
 
diff --git a/pandas/core/series.py b/pandas/core/series.py
index 4f9465354a47b..f9c9c3ab81937 100644
--- a/pandas/core/series.py
+++ b/pandas/core/series.py
@@ -134,9 +134,10 @@ class Series(base.IndexOpsMixin, generic.NDFrame):
     """
     _metadata = ['name']
     _accessors = {'dt', 'cat', 'str', 'sparse'}
+    # tolist is not actually deprecated, just suppressed in the __dir__
     _deprecations = generic.NDFrame._deprecations | frozenset(
         ['asobject', 'reshape', 'get_value', 'set_value',
-         'from_csv', 'valid'])
+         'from_csv', 'valid', 'tolist'])
 
     # Override cache_readonly bc Series is mutable
     hasnans = property(base.IndexOpsMixin.hasnans.func,
diff --git a/pandas/tests/test_base.py b/pandas/tests/test_base.py
index 47fafe2a900b4..9f0def034f976 100644
--- a/pandas/tests/test_base.py
+++ b/pandas/tests/test_base.py
@@ -1099,9 +1099,10 @@ class TestToIterable(object):
         'method',
         [
             lambda x: x.tolist(),
+            lambda x: x.to_list(),
             lambda x: list(x),
             lambda x: list(x.__iter__()),
-        ], ids=['tolist', 'list', 'iter'])
+        ], ids=['tolist', 'to_list', 'list', 'iter'])
     @pytest.mark.parametrize('typ', [Series, Index])
     def test_iterable(self, typ, method, dtype, rdtype):
         # gh-10904
@@ -1122,9 +1123,10 @@ def test_iterable(self, typ, method, dtype, rdtype):
         'method',
         [
             lambda x: x.tolist(),
+            lambda x: x.to_list(),
             lambda x: list(x),
             lambda x: list(x.__iter__()),
-        ], ids=['tolist', 'list', 'iter'])
+        ], ids=['tolist', 'to_list', 'list', 'iter'])
     @pytest.mark.parametrize('typ', [Series, Index])
     def test_iterable_object_and_category(self, typ, method,
                                           dtype, rdtype, obj):
@@ -1167,9 +1169,10 @@ def test_iterable_map(self, typ, dtype, rdtype):
         'method',
         [
             lambda x: x.tolist(),
+            lambda x: x.to_list(),
             lambda x: list(x),
             lambda x: list(x.__iter__()),
-        ], ids=['tolist', 'list', 'iter'])
+        ], ids=['tolist', 'to_list', 'list', 'iter'])
     def test_categorial_datetimelike(self, method):
         i = CategoricalIndex([Timestamp('1999-12-31'),
                               Timestamp('2000-12-31')])


Code review comments:
diff_hunk: @@ -1071,6 +1071,7 @@ Other API Changes
 - :meth:`Index.hasnans` and :meth:`Series.hasnans` now always return a python boolean. Previously, a python or a numpy boolean could be returned, depending on circumstances (:issue:`23294`).
 - The order of the arguments of :func:`DataFrame.to_html` and :func:`DataFrame.to_string` is rearranged to be consistent with each other. (:issue:`23614`)
 - :meth:`CategoricalIndex.reindex` now raises a ``ValueError`` if the target index is non-unique and not equal to the current index. It previously only raised if the target index was not of a categorical dtype (:issue:`23963`).
+- :func:`Series.tolist` and :func:`Index.tolist()` now have an alias ``to_list`` (:issue:`8826`)
path: doc/source/whatsnew/v0.24.0.rst
text: @user1:
this will no longer render as ``Series.tolist`` doesn't exist, so reverse this, something like
``:func:`Series.to_list` `` and ..... are an alias for ``Series.to_list`` ....

@author:
Fixed