baby_names = {
"cat": "kitten",
"dog": "puppy",
}
print(baby_names){'cat': 'kitten', 'dog': 'puppy'}
{'cat': 'kitten', 'dog': 'puppy'}
{'dog': 'puppy', 'cat', 'kitten'}
While Insertion ordering was introduced in Python 3.6, it only formally became part of the specification in Python 3.7. If using Python 3.6 check that your interpreter supports insertion ordering
keys
values
popitem
baby_names = {
"cat": "kitten",
"dog": "puppy",
}
keys = list(baby_names.keys())
values = list(baby_names.values())
items = list(baby_names.items())
print(f"last_item: {baby_names.popitem()}") # Last item inserted like a stack
assert keys == ["cat", "dog"]
assert values == ["kitten", "puppy"]
assert items == [("cat", "kitten"), ("dog", "puppy")]last_item: ('dog', 'puppy')
**kwargs would be randomly ordereddict to keep track of their instance attributes__dict__ attributeOrderedDict
The collections built-in module provides the OrderedDict class which preserves the insertion order. This can be used in python versions that predate 3.6 / 3.7. However, while the behaviour is similar the under the hood implementation differs and the two have different performance characteristics. For high rates of key insertion and popitem calls (e.g. When implementing a least-recently-used cache), OrderedDict may provide better performance than a standard dict
def populate_ranks(votes, ranks):
names = list(votes.keys())
names.sort(key=votes.get, reverse=True)
for i, name in enumerate(names, start=1):
ranks[name] = i
def get_winner(ranks):
return next(iter(ranks))
votes = {
"otter": 1281,
"polar bear": 587,
"fox": 863,
}
ranks = {}
populate_ranks(votes, ranks)
print(ranks)
winner = get_winner(ranks)
print(winner){'otter': 1, 'fox': 2, 'polar bear': 3}
otter
collections.abc (built-in module for abstract collections) to define a class with a dictionary-like interface
MutableMapping classdict is called a Mapping, effectively the generic term for a key-value lookup containerMutable means the container can be modifiedfrom collections.abc import MutableMapping
class SortedDict(MutableMapping):
def __init__(self):
self.data = {}
def __getitem__(self, key):
return self.data[key]
def __setitem__(self, key, value):
self.data[key] = value
def __delitem__(self, key):
del self.data[key]
def __iter__(self):
keys = list(self.data.keys())
keys.sort()
for key in keys:
yield key
def __len__(self):
return len(self.data)SortedDict conforms to the dict protocol
dictfrom collections.abc import MutableMapping
class SortedDict(MutableMapping):
def __init__(self):
self.data = {}
def __getitem__(self, key):
return self.data[key]
def __setitem__(self, key, value):
self.data[key] = value
def __delitem__(self, key):
del self.data[key]
def __iter__(self):
keys = list(self.data.keys())
keys.sort()
for key in keys:
yield key
def __len__(self):
return len(self.data)
def populate_ranks(votes, ranks):
names = list(votes.keys())
names.sort(key=votes.get, reverse=True)
for i, name in enumerate(names, start=1):
ranks[name] = i
def get_winner(ranks):
return next(iter(ranks))
votes = {
"otter": 1281,
"polar bear": 587,
"fox": 863,
}
sorted_ranks = SortedDict()
populate_ranks(votes, sorted_ranks)
print(sorted_ranks.data)
winner = get_winner(sorted_ranks)
print(winner){'otter': 1, 'fox': 2, 'polar bear': 3}
fox
fox the winner
get_winner is relying on the dictionary being insertion-ordered in decreasing rankfox is alphabetically first and so is returned by overloaded SortedDict classget_winner to assume no Iteration Orderfrom collections.abc import MutableMapping
class SortedDict(MutableMapping):
def __init__(self):
self.data = {}
def __getitem__(self, key):
return self.data[key]
def __setitem__(self, key, value):
self.data[key] = value
def __delitem__(self, key):
del self.data[key]
def __iter__(self):
keys = list(self.data.keys())
keys.sort()
for key in keys:
yield key
def __len__(self):
return len(self.data)
def populate_ranks(votes, ranks):
names = list(votes.keys())
names.sort(key=votes.get, reverse=True)
for i, name in enumerate(names, start=1):
ranks[name] = i
# Reimplemented without assumed ordering
def get_winner(ranks):
for name, rank in ranks.items():
if rank == 1:
return name
votes = {
"otter": 1281,
"polar bear": 587,
"fox": 863,
}
sorted_ranks = SortedDict()
populate_ranks(votes, sorted_ranks)
print(sorted_ranks.data)
winner = get_winner(sorted_ranks)
print(winner){'otter': 1, 'fox': 2, 'polar bear': 3}
otter
rank Objectisinstance to enforce that we have the expected typefrom collections.abc import MutableMapping
class SortedDict(MutableMapping):
def __init__(self):
self.data = {}
def __getitem__(self, key):
return self.data[key]
def __setitem__(self, key, value):
self.data[key] = value
def __delitem__(self, key):
del self.data[key]
def __iter__(self):
keys = list(self.data.keys())
keys.sort()
for key in keys:
yield key
def __len__(self):
return len(self.data)
def populate_ranks(votes, ranks):
names = list(votes.keys())
names.sort(key=votes.get, reverse=True)
for i, name in enumerate(names, start=1):
ranks[name] = i
# Reimplemented without assumed ordering
def get_winner(ranks):
if not isinstance(ranks, dict):
raise TypeError("must provide a dict instance")
return next(iter(ranks))
votes = {
"otter": 1281,
"polar bear": 587,
"fox": 863,
}
sorted_ranks = SortedDict()
populate_ranks(votes, sorted_ranks)
print(sorted_ranks.data)
print("Passing the underlying dict from the sorted_ranks SortedDict")
winner = get_winner(sorted_ranks.data)
print(winner)
print("Passing the sorted_ranks SortedDict directly...")
winner = get_winner(sorted_ranks)
print(winner){'otter': 1, 'fox': 2, 'polar bear': 3}
Passing the underlying dict from the sorted_ranks SortedDict
otter
Passing the sorted_ranks SortedDict directly...
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) Cell In[11], line 56 53 print(winner) 55 print("Passing the sorted_ranks SortedDict directly...") ---> 56 winner = get_winner(sorted_ranks) 57 print(winner) Cell In[11], line 37, in get_winner(ranks) 35 def get_winner(ranks): 36 if not isinstance(ranks, dict): ---> 37 raise TypeError("must provide a dict instance") 38 return next(iter(ranks)) TypeError: must provide a dict instance
rank parameter is a dict instance not a MutableMapping (that behaves like a dictionary)from collections.abc import MutableMapping
from typing import Dict, MutableMapping
class SortedDict(MutableMapping[str, int]):
def __init__(self):
self.data = {}
def __getitem__(self, key):
return self.data[key]
def __setitem__(self, key, value):
self.data[key] = value
def __delitem__(self, key):
del self.data[key]
def __iter__(self):
keys = list(self.data.keys())
keys.sort()
for key in keys:
yield key
def __len__(self):
return len(self.data)
def populate_ranks(votes: Dict[str, int], ranks: Dict[str, int]) -> None:
names = list(votes.keys())
names.sort(key=votes.get, reverse=True)
for i, name in enumerate(names, start=1):
ranks[name] = i
# Reimplemented without assumed ordering
def get_winner(ranks: Dict[str, int]) -> str:
return next(iter(ranks))
votes = {
"otter": 1281,
"polar bear": 587,
"fox": 863,
}
sorted_ranks = SortedDict()
populate_ranks(votes, sorted_ranks)
print(sorted_ranks.data)
print("Passing the underlying dict from the sorted_ranks SortedDict")
winner = get_winner(sorted_ranks.data)
print(winner)
print("Passing the sorted_ranks SortedDict directly...")
winner = get_winner(sorted_ranks)
print(winner){'otter': 1, 'fox': 2, 'polar bear': 3}
Passing the underlying dict from the sorted_ranks SortedDict
otter
Passing the sorted_ranks SortedDict directly...
fox
|
46 | sorted_ranks = SortedDict()
47 | populate_ranks(votes, sorted_ranks)
| ^^^^^^^^^^^^ Expected `dict[str, int]`, found `SortedDict`
48 | print(sorted_ranks.data)
|
info: Function defined here
--> type_checking.py:28:5
|
28 | def populate_ranks(votes: Dict[str, int], ranks: Dict[str, int]) -> None:
| ^^^^^^^^^^^^^^ --------------------- Parameter declared here
29 | names = list(votes.keys())
30 | names.sort(key=votes.__getitem__, reverse=True)
|
info: rule `invalid-argument-type` is enabled by default
error[invalid-argument-type]: Argument to function `get_winner` is incorrect
--> type_checking.py:55:21
|
54 | print("Passing the sorted_ranks SortedDict directly...")
55 | winner = get_winner(sorted_ranks)
| ^^^^^^^^^^^^ Expected `dict[str, int]`, found `SortedDict`
56 | print(winner)
|
info: Function defined here
--> type_checking.py:36:5
|
35 | # Reimplemented without assumed ordering
36 | def get_winner(ranks: Dict[str, int]) -> str:
| ^^^^^^^^^^ --------------------- Parameter declared here
37 | return next(iter(ranks))
|
info: rule `invalid-argument-type` is enabled by default
dict
isinstance to perform runtime type checks for the dict type