Skip to content

Commit f28aff6

Browse files
authored
Core: Replace generator creation/iteration in CollectionState methods (#4587)
* Core: Replace generator creation/iteration in CollectionState methods Using generators in these functions incurs overhead to create the new generator instance, call the `any`/`all`/`sum` function and have the `any`/`all`/`sum` function iterate the generator, which in turn iterates the iterable. Replacing the use of generators with for loops is faster. Getting `self.prog_items[player]` once in advance also improves performance of iterating longer iterables. * Add comment on the choice of for loops instead of any()/all()/sum()
1 parent 894732b commit f28aff6

File tree

1 file changed

+34
-6
lines changed

1 file changed

+34
-6
lines changed

BaseClasses.py

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -869,21 +869,40 @@ def sweep_for_advancements(self, locations: Optional[Iterable[Location]] = None)
869869
def has(self, item: str, player: int, count: int = 1) -> bool:
870870
return self.prog_items[player][item] >= count
871871

872+
# for loops are specifically used in all/any/count methods, instead of all()/any()/sum(), to avoid the overhead of
873+
# creating and iterating generator instances. In `return all(player_prog_items[item] for item in items)`, the
874+
# argument to all() would be a new generator instance, for example.
872875
def has_all(self, items: Iterable[str], player: int) -> bool:
873876
"""Returns True if each item name of items is in state at least once."""
874-
return all(self.prog_items[player][item] for item in items)
877+
player_prog_items = self.prog_items[player]
878+
for item in items:
879+
if not player_prog_items[item]:
880+
return False
881+
return True
875882

876883
def has_any(self, items: Iterable[str], player: int) -> bool:
877884
"""Returns True if at least one item name of items is in state at least once."""
878-
return any(self.prog_items[player][item] for item in items)
885+
player_prog_items = self.prog_items[player]
886+
for item in items:
887+
if player_prog_items[item]:
888+
return True
889+
return False
879890

880891
def has_all_counts(self, item_counts: Mapping[str, int], player: int) -> bool:
881892
"""Returns True if each item name is in the state at least as many times as specified."""
882-
return all(self.prog_items[player][item] >= count for item, count in item_counts.items())
893+
player_prog_items = self.prog_items[player]
894+
for item, count in item_counts.items():
895+
if player_prog_items[item] < count:
896+
return False
897+
return True
883898

884899
def has_any_count(self, item_counts: Mapping[str, int], player: int) -> bool:
885900
"""Returns True if at least one item name is in the state at least as many times as specified."""
886-
return any(self.prog_items[player][item] >= count for item, count in item_counts.items())
901+
player_prog_items = self.prog_items[player]
902+
for item, count in item_counts.items():
903+
if player_prog_items[item] >= count:
904+
return True
905+
return False
887906

888907
def count(self, item: str, player: int) -> int:
889908
return self.prog_items[player][item]
@@ -911,11 +930,20 @@ def has_from_list_unique(self, items: Iterable[str], player: int, count: int) ->
911930

912931
def count_from_list(self, items: Iterable[str], player: int) -> int:
913932
"""Returns the cumulative count of items from a list present in state."""
914-
return sum(self.prog_items[player][item_name] for item_name in items)
933+
player_prog_items = self.prog_items[player]
934+
total = 0
935+
for item_name in items:
936+
total += player_prog_items[item_name]
937+
return total
915938

916939
def count_from_list_unique(self, items: Iterable[str], player: int) -> int:
917940
"""Returns the cumulative count of items from a list present in state. Ignores duplicates of the same item."""
918-
return sum(self.prog_items[player][item_name] > 0 for item_name in items)
941+
player_prog_items = self.prog_items[player]
942+
total = 0
943+
for item_name in items:
944+
if player_prog_items[item_name] > 0:
945+
total += 1
946+
return total
919947

920948
# item name group related
921949
def has_group(self, item_name_group: str, player: int, count: int = 1) -> bool:

0 commit comments

Comments
 (0)