diff --git a/src/uproot/reading.py b/src/uproot/reading.py index e8d52fdd2..01d6cd51d 100644 --- a/src/uproot/reading.py +++ b/src/uproot/reading.py @@ -1444,12 +1444,19 @@ def __init__(self, path, cursor, context, file, parent): ) self._keys = [] + self._keys_lookup = {} for _ in range(num_keys): key = ReadOnlyKey( keys_chunk, keys_cursor, {}, file, self, read_strings=True ) + name = key.fName + if name not in self._keys_lookup: + self._keys_lookup[name] = [] + self._keys_lookup[name].append(len(self._keys)) self._keys.append(key) + self._len = None + self.hook_after_keys( chunk=chunk, cursor=cursor, @@ -1901,11 +1908,13 @@ def _ipython_key_completions_(self): return self.iterkeys() # noqa: B301 (not a dict) def __len__(self): - return len(self._keys) + sum( - len(x.get()) - for x in self._keys - if x.fClassName in ("TDirectory", "TDirectoryFile") - ) + if self._len is None: + self._len = len(self._keys) + sum( + len(x.get()) + for x in self._keys + if x.fClassName in ("TDirectory", "TDirectoryFile") + ) + return self._len def __contains__(self, where): try: @@ -2031,14 +2040,14 @@ def key(self, where): item, cycle = where, None last = None - for key in self._keys: - if key.fName == item: - if cycle == key.fCycle: - return key - elif cycle is None and last is None: - last = key - elif cycle is None and last.fCycle < key.fCycle: - last = key + for index in self._keys_lookup.get(item, []): + key = self._keys[index] + if cycle == key.fCycle: + return key + elif cycle is None and last is None: + last = key + elif cycle is None and last.fCycle < key.fCycle: + last = key if last is not None: return last