| 529 | return cls(layers, deps) |
| 530 | |
| 531 | def __getitem__(self, key: Key) -> Any: |
| 532 | # Attempt O(1) direct access first, under the assumption that layer names match |
| 533 | # either the keys (Scalar, Item, Delayed) or the first element of the key tuples |
| 534 | # (Array, Bag, DataFrame, Series). This assumption is not always true. |
| 535 | try: |
| 536 | return self.layers[key][key] # type: ignore[index] |
| 537 | except KeyError: |
| 538 | pass |
| 539 | try: |
| 540 | return self.layers[key[0]][key] # type: ignore[index] |
| 541 | except (KeyError, IndexError, TypeError): |
| 542 | pass |
| 543 | |
| 544 | # Fall back to O(n) access |
| 545 | for d in self.layers.values(): |
| 546 | try: |
| 547 | return d[key] |
| 548 | except KeyError: |
| 549 | pass |
| 550 | |
| 551 | raise KeyError(key) |
| 552 | |
| 553 | def __len__(self) -> int: |
| 554 | # NOTE: this will double-count keys that are duplicated between layers, so it's |