Efficiently combining, counting, and iterating

Writing Efficient Python Code

Logan Thomas

Scientific Software Technical Trainer, Enthought

Pokémon Overview

  • Trainers (collect Pokémon)

alt=”Ash Ketchum; one of the many characters (called trainers) in the Nintendo video game Pokémon”

Writing Efficient Python Code

Pokémon Overview

  • Pokémon (fictional animal characters)

alt=”Squirtle, Pikachu, Bulbasaur, and Charmander; a few of the many Pokémon that exist in the Nintendo video game”

Writing Efficient Python Code

Pokémon Overview

  • Pokédex (stores captured Pokémon)

alt=”Pokédex, a tool used by trainers to store captured Pokémon”

Writing Efficient Python Code

Pokémon Description

alt=”The Pokémon named Squirtle along with its accompanying metadata”

Writing Efficient Python Code

Pokémon Description

alt=”The Pokémon named Squirtle along with its accompanying metadata and the Name and Generation field highlighted”

Writing Efficient Python Code

Pokémon Description

alt=”The Pokémon named Squirtle along with its accompanying metadata and the Type and Legendary field highlighted”

Writing Efficient Python Code

Pokémon Description

alt=”The Pokémon named Squirtle along with its accompanying metadata and the Health Points, Attack, Defense, Special Attack, Special Defense, Speed, and Total fields highlighted”

Writing Efficient Python Code

Combining objects

names = ['Bulbasaur', 'Charmander', 'Squirtle']
hps = [45, 39, 44]
combined = []

for i,pokemon in enumerate(names):
    combined.append((pokemon, hps[i]))

print(combined)
[('Bulbasaur', 45), ('Charmander', 39), ('Squirtle', 44)]
Writing Efficient Python Code

Combining objects with zip

names = ['Bulbasaur', 'Charmander', 'Squirtle']
hps = [45, 39, 44]
combined_zip = zip(names, hps)

print(type(combined_zip))
<class 'zip'>
combined_zip_list = [*combined_zip]

print(combined_zip_list)
[('Bulbasaur', 45), ('Charmander', 39), ('Squirtle', 44)]
Writing Efficient Python Code

The collections module

  • Part of Python's Standard Library (built-in module)
  • Specialized container datatypes
    • Alternatives to general purpose dict, list, set, and tuple
  • Notable:
    • namedtuple: tuple subclasses with named fields
    • deque: list-like container with fast appends and pops
    • Counter: dict for counting hashable objects
    • OrderedDict: dict that retains order of entries
    • defaultdict: dict that calls a factory function to supply missing values
Writing Efficient Python Code

The collections module

  • Part of Python's Standard Library (built-in module)
  • Specialized container datatypes
    • Alternatives to general purpose dict, list, set, and tuple
  • Notable:
    • namedtuple: tuple subclasses with named fields
    • deque: list-like container with fast appends and pops
    • Counter: dict for counting hashable objects
    • OrderedDict: dict that retains order of entries
    • defaultdict: dict that calls a factory function to supply missing values
Writing Efficient Python Code

Counting with loop

# Each Pokémon's type (720 total)
poke_types = ['Grass', 'Dark', 'Fire', 'Fire', ...]

type_counts = {}
for poke_type in poke_types: if poke_type not in type_counts: type_counts[poke_type] = 1 else: type_counts[poke_type] += 1
print(type_counts)
{'Rock': 41, 'Dragon': 25, 'Ghost': 20, 'Ice': 23, 'Poison': 28, 'Grass': 64,
 'Flying': 2, 'Electric': 40, 'Fairy': 17, 'Steel': 21, 'Psychic': 46, 'Bug': 65,
 'Dark': 28, 'Fighting': 25, 'Ground': 30, 'Fire': 48,'Normal': 92, 'Water': 105}
Writing Efficient Python Code

collections.Counter()

# Each Pokémon's type (720 total)
poke_types = ['Grass', 'Dark', 'Fire', 'Fire', ...]

from collections import Counter
type_counts = Counter(poke_types)
print(type_counts)
Counter({'Water': 105, 'Normal': 92, 'Bug': 65, 'Grass': 64, 'Fire': 48,
         'Psychic': 46, 'Rock': 41, 'Electric': 40, 'Ground': 30,
         'Poison': 28, 'Dark': 28, 'Dragon': 25, 'Fighting': 25, 'Ice': 23,
         'Steel': 21, 'Ghost': 20, 'Fairy': 17, 'Flying': 2})
Writing Efficient Python Code

The itertools module

  • Part of Python's Standard Library (built-in module)
  • Functional tools for creating and using iterators
  • Notable:
    • Infinite iterators: count, cycle, repeat
    • Finite iterators: accumulate, chain, zip_longest, etc.
    • Combination generators: product, permutations, combinations
Writing Efficient Python Code

The itertools module

  • Part of Python's Standard Library (built-in module)
  • Functional tools for creating and using iterators
  • Notable:
    • Infinite iterators: count, cycle, repeat
    • Finite iterators: accumulate, chain, zip_longest, etc.
    • Combination generators: product, permutations, combinations
Writing Efficient Python Code

Combinations with loop

poke_types = ['Bug', 'Fire', 'Ghost', 'Grass', 'Water']

combos = [] for x in poke_types: for y in poke_types: if x == y: continue if ((x,y) not in combos) & ((y,x) not in combos): combos.append((x,y))
print(combos)
[('Bug', 'Fire'), ('Bug', 'Ghost'), ('Bug', 'Grass'), ('Bug', 'Water'),
 ('Fire', 'Ghost'), ('Fire', 'Grass'), ('Fire', 'Water'),
 ('Ghost', 'Grass'), ('Ghost', 'Water'), ('Grass', 'Water')]
Writing Efficient Python Code

itertools.combinations()

poke_types = ['Bug', 'Fire', 'Ghost', 'Grass', 'Water']

from itertools import combinations
combos_obj = combinations(poke_types, 2)
print(type(combos_obj))
<class 'itertools.combinations'>
combos = [*combos_obj]
print(combos)
[('Bug', 'Fire'), ('Bug', 'Ghost'), ('Bug', 'Grass'), ('Bug', 'Water'),
 ('Fire', 'Ghost'), ('Fire', 'Grass'), ('Fire', 'Water'),
 ('Ghost', 'Grass'), ('Ghost', 'Water'), ('Grass', 'Water')]
Writing Efficient Python Code

Let's practice!

Writing Efficient Python Code

Preparing Video For Download...