diff --git a/pandas/core/indexes/multi.py b/pandas/core/indexes/multi.py index c560d81ba95f6..ea29e458fe10e 100644 --- a/pandas/core/indexes/multi.py +++ b/pandas/core/indexes/multi.py @@ -677,8 +677,11 @@ def __len__(self) -> int: # -------------------------------------------------------------------- # Levels Methods - @property + @cache_readonly def levels(self): + # Use cache_readonly to ensure that self.get_locs doesn't repeatedly + # create new IndexEngine + # https://github.com/pandas-dev/pandas/issues/31648 result = [ x._shallow_copy(name=name) for x, name in zip(self._levels, self._names) ] @@ -1302,6 +1305,9 @@ def _set_names(self, names, level=None, validate=True): ) self._names[lev] = name + # If .levels has been accessed, the names in our cache will be stale. + self._reset_cache() + names = property( fset=_set_names, fget=_get_names, doc="""\nNames of levels in MultiIndex.\n""" ) diff --git a/pandas/tests/indexes/multi/test_get_set.py b/pandas/tests/indexes/multi/test_get_set.py index 074072ae581b2..57d16a739c213 100644 --- a/pandas/tests/indexes/multi/test_get_set.py +++ b/pandas/tests/indexes/multi/test_get_set.py @@ -159,7 +159,7 @@ def test_set_levels_codes_directly(idx): minor_codes = [(x + 1) % 1 for x in minor_codes] new_codes = [major_codes, minor_codes] - msg = "can't set attribute" + msg = "[Cc]an't set attribute" with pytest.raises(AttributeError, match=msg): idx.levels = new_levels with pytest.raises(AttributeError, match=msg):