Skip to content

Commit 3b2b0d3

Browse files
PERF: Cache MultiIndex.levels (#31651)
* PERF: Cache MultiIndex.levels Closes #31648 * fixup tests
1 parent d28db65 commit 3b2b0d3

File tree

2 files changed

+8
-2
lines changed

2 files changed

+8
-2
lines changed

pandas/core/indexes/multi.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -677,8 +677,11 @@ def __len__(self) -> int:
677677
# --------------------------------------------------------------------
678678
# Levels Methods
679679

680-
@property
680+
@cache_readonly
681681
def levels(self):
682+
# Use cache_readonly to ensure that self.get_locs doesn't repeatedly
683+
# create new IndexEngine
684+
# https://github.com/pandas-dev/pandas/issues/31648
682685
result = [
683686
x._shallow_copy(name=name) for x, name in zip(self._levels, self._names)
684687
]
@@ -1302,6 +1305,9 @@ def _set_names(self, names, level=None, validate=True):
13021305
)
13031306
self._names[lev] = name
13041307

1308+
# If .levels has been accessed, the names in our cache will be stale.
1309+
self._reset_cache()
1310+
13051311
names = property(
13061312
fset=_set_names, fget=_get_names, doc="""\nNames of levels in MultiIndex.\n"""
13071313
)

pandas/tests/indexes/multi/test_get_set.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ def test_set_levels_codes_directly(idx):
159159
minor_codes = [(x + 1) % 1 for x in minor_codes]
160160
new_codes = [major_codes, minor_codes]
161161

162-
msg = "can't set attribute"
162+
msg = "[Cc]an't set attribute"
163163
with pytest.raises(AttributeError, match=msg):
164164
idx.levels = new_levels
165165
with pytest.raises(AttributeError, match=msg):

0 commit comments

Comments
 (0)