Extra Topic: More on sets and dicts


Note: extra topics are not in CS Academy, but are required and can appear on any future homework, writing session, quiz, or exam.

frozensets (immutable sets)

Sets are mutable, but frozensets are immutable:

# sets are mutable: s = { 2, 3, 5 } s.add(7) # <-- mutates s print(s) # {2, 3, 5, 7} # frozensets are immutable: fs = frozenset(s) try: fs.add(11) except: print('Cannot call fs.add(11) because frozensets are immutable.')

Sets are not hashable, but frozensets are hashable:

# sets are not hashable: s = { 2, 3, 5, 7 } try: print(f'hash(s) = {hash(s)}') except: print('Cannot call hash(s) because sets are not hashable.') # frozensets are hashable: fs = frozenset(s) print(f'hash(fs) = {hash(fs)}')

Sets cannot be keys in dicts, but frozensets can be keys in dicts:

# sets cannot be keys in dicts: s = { 2, 3, 5, 7 } try: print({s : 42}) except: print('Cannot call use s as a key in a dict') # frozensets are hashable: fs = frozenset(s) print({fs: 42})

dict.keys() and dict.values()

Basic use:

d = {'PA': 17, 'OH': 15} # Use d.keys() to loop over the keys: print('Keys:') for key in d.keys(): print(key) # Use d.values() to loop over the values: print('Values:') for value in d.values(): print(value)

Wrap in list() to convert to a list:

d = {'PA': 17, 'OH': 15} # Note that d.keys() and d.values() have unexpected types: print(d.keys()) # dict_keys(['PA', 'OH']) print(d.values()) # dict_values([17, 15]) # use list(d.keys()) and list(d.values()) to convert them to lists: print(list(d.keys())) # ['PA', 'OH'] print(list(d.values())) # [17, 15]

defaultdicts

A defaultdict uses a default value (instead of crashing) for missing keys:

from collections import defaultdict # instead of this: d = dict() L = [2, 4, 2, 5, 4, 2] for v in L: d[v] = d.get(v, 0) + 1 print(d) # {2: 3, 4: 2, 5: 1} # you can do this: d = defaultdict(int) # <-- This makes a dict which defaults to 0 for missing keys L = [2, 4, 2, 5, 4, 2] for v in L: d[v] += 1 # <-- This is where the magic happens print(d) # defaultdict(<class 'int'>, {2: 3, 4: 2, 5: 1}) print(isinstance(d, dict)) # True

Counter

A Counter is the easiest way to get a count of values in an iterable (like a list or string):

from collections import Counter # instead of this: d = dict() L = [2, 4, 2, 5, 4, 2] for v in L: d[v] = d.get(v, 0) + 1 print(d) # {2: 3, 4: 2, 5: 1} # you can do this: L = [2, 4, 2, 5, 4, 2] d = Counter(L) print(d) # Counter({2: 3, 4: 2, 5: 1}) print(isinstance(d, dict)) # True