From 4cada2f2224919b14cf9ed7ccd777e607cef5be7 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Tue, 11 Feb 2020 17:50:38 -0800 Subject: [PATCH] REF: implement unpack_1tuple to clean up Series.__getitem__ --- pandas/core/indexers.py | 27 +++++++++++++++++++++++++++ pandas/core/series.py | 35 +++++------------------------------ 2 files changed, 32 insertions(+), 30 deletions(-) diff --git a/pandas/core/indexers.py b/pandas/core/indexers.py index fe475527f4596..3f6bcf0ab5cfa 100644 --- a/pandas/core/indexers.py +++ b/pandas/core/indexers.py @@ -270,6 +270,33 @@ def deprecate_ndim_indexing(result): ) +def unpack_1tuple(tup): + """ + If we have a length-1 tuple/list that contains a slice, unpack to just + the slice. + + Notes + ----- + The list case is deprecated. + """ + if len(tup) == 1 and isinstance(tup[0], slice): + # if we don't have a MultiIndex, we may still be able to handle + # a 1-tuple. see test_1tuple_without_multiindex + + if isinstance(tup, list): + # GH#31299 + warnings.warn( + "Indexing with a single-item list containing a " + "slice is deprecated and will raise in a future " + "version. Pass a tuple instead.", + FutureWarning, + stacklevel=3, + ) + + return tup[0] + return tup + + # ----------------------------------------------------------- # Public indexer validation diff --git a/pandas/core/series.py b/pandas/core/series.py index 7d74d32bf5e14..0b978e5748d3a 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -73,7 +73,7 @@ is_empty_data, sanitize_array, ) -from pandas.core.indexers import maybe_convert_indices +from pandas.core.indexers import maybe_convert_indices, unpack_1tuple from pandas.core.indexes.accessors import CombinedDatetimelikeProperties from pandas.core.indexes.api import ( Float64Index, @@ -854,6 +854,8 @@ def __getitem__(self, key): key_is_scalar = is_scalar(key) if key_is_scalar: key = self.index._convert_scalar_indexer(key, kind="getitem") + elif isinstance(key, (list, tuple)): + key = unpack_1tuple(key) if key_is_scalar or isinstance(self.index, MultiIndex): # Otherwise index.get_value will raise InvalidIndexError @@ -896,16 +898,7 @@ def _get_with(self, key): "supported, use the appropriate DataFrame column" ) elif isinstance(key, tuple): - try: - return self._get_values_tuple(key) - except ValueError: - # if we don't have a MultiIndex, we may still be able to handle - # a 1-tuple. see test_1tuple_without_multiindex - if len(key) == 1: - key = key[0] - if isinstance(key, slice): - return self._get_values(key) - raise + return self._get_values_tuple(key) if not isinstance(key, (list, np.ndarray, ExtensionArray, Series, Index)): key = list(key) @@ -927,26 +920,8 @@ def _get_with(self, key): else: return self.iloc[key] - if isinstance(key, (list, tuple)): - # TODO: de-dup with tuple case handled above? + if isinstance(key, list): # handle the dup indexing case GH#4246 - if len(key) == 1 and isinstance(key[0], slice): - # [slice(0, 5, None)] will break if you convert to ndarray, - # e.g. as requested by np.median - # FIXME: hack - if isinstance(key, list): - # GH#31299 - warnings.warn( - "Indexing with a single-item list containing a " - "slice is deprecated and will raise in a future " - "version. Pass a tuple instead.", - FutureWarning, - stacklevel=3, - ) - # TODO: use a message more like numpy's? - key = tuple(key) - return self._get_values(key) - return self.loc[key] return self.reindex(key)