๐ Python Dictionaries and Bad Vexillology Design#
In this notebook, we will explore Python dictionaries using the theme of bad vexillology (flag design). Weโll use examples of poorly designed flags to understand dictionary concepts, methods, advantages, and limitations.
Bad Flag Design Elements#
Too Complex: Intricate designs or details that are hard to see and replicate.
Cluttered: Overloaded with symbols, colors, or themes.
Poor Colors: Clashing, low-contrast, or overly similar colors.
Text: Words or slogans that are unreadable when waving.
No Symbolism: Random imagery with no clear meaning.
San Francisco Flag#
bad_flag = {
"country": "Confusistan",
"colors": ["red", "green", "purple", "neon yellow"],
"symbols": ["star", "dragon", "rainbow", "text: 'Unity'"],
"design_complexity": "Extremely High",
"readability": "Unreadable",
}
print("Bad Flag Example:")
print(bad_flag)
Bad Flag Example:
{'country': 'Confusistan', 'colors': ['red', 'green', 'purple', 'neon yellow'], 'symbols': ['star', 'dragon', 'rainbow', "text: 'Unity'"], 'design_complexity': 'Extremely High', 'readability': 'Unreadable'}
Definition and Syntax#
Milwaukee Flag#
Definition
A dictionary is an ordered, mutable collection of key-value pairs in Python. Keys must be unique and immutable, while values can be any type.
Syntax
d = {"key1": value1, "key2": value2}
Examples:
{ "name": "White House", "location": "Beijing" }
{ 1: "one", 2: "two", 3: "three" }
{ "x": 42, "y": 3.14 }
Note
Dictionaries in Python were unordered before version 3.7. Since Python 3.7, dictionaries maintain the insertion order.
Updating Dictionary Elements#
You can update key-value pairs using the =
assignment operator. Where the variable is the dictionary and the new key is in square brackets.
You can also use the update()
method to add multiple key-value pairs to a dictionary.
bad_flag["controversy"] = "Offensive design choices"
print("\nUpdated Bad Flag Dictionary:")
print(bad_flag)
Updated Bad Flag Dictionary:
{'country': 'Confusistan', 'colors': ['red', 'green', 'purple', 'neon yellow'], 'symbols': ['star', 'dragon', 'rainbow', "text: 'Unity'"], 'design_complexity': 'Extremely High', 'readability': 'Unreadable', 'controversy': 'Offensive design choices'}
Note
in a string \ is used as an escape character. This means that it is used to represent characters that are not allowed in the string. For instance, the single quote character (โ) is not allowed in a string delineated by single quotes. If you want to include a single quote character in a string delineated by single quotes, you must use the escape character like this: โ, in the previous example we used \n which is used to represent a new line.
Extracting Values#
You can extract values from a dictionary using the key in square brackets.
print("\nAccessing a value:")
print("Colors in the flag:", bad_flag["colors"])
Accessing a value:
Colors in the flag: ['red', 'green', 'purple', 'neon yellow']
Adding a New Key-Value Pair#
You can add a new key-value pair to a dictionary by assigning a value to a new key.The variable is the dictionary and the new key is in square brackets.
bad_flag["public_opinion"] = "Negative"
print("\nAdding a new key-value pair for 'public_opinion':")
print(bad_flag)
Adding a new key-value pair for 'public_opinion':
{'country': 'Confusistan', 'colors': ['red', 'green', 'purple', 'neon yellow'], 'symbols': ['star', 'dragon', 'rainbow', "text: 'Unity'"], 'design_complexity': 'Extremely High', 'readability': 'Unreadable', 'controversy': 'Offensive design choices', 'public_opinion': 'Negative'}
Removing a Key-Value Pair#
You can remove a key-value pair from a dictionary using the pop()
method. The key is passed as an argument to the method.
bad_flag.pop("controversy")
print("\nRemoving the 'controversy' key:")
print(bad_flag)
Removing the 'controversy' key:
{'country': 'Confusistan', 'colors': ['red', 'green', 'purple', 'neon yellow'], 'symbols': ['star', 'dragon', 'rainbow', "text: 'Unity'"], 'design_complexity': 'Extremely High', 'readability': 'Unreadable', 'public_opinion': 'Negative'}
Getting All Keys and Values#
You can get all keys and values from a dictionary using the keys()
and values()
methods, respectively.
print("\nGetting all the keys:")
print("Keys:", bad_flag.keys())
print("\nGetting all the values:")
print("Values:", bad_flag.values())
Getting all the keys:
Keys: dict_keys(['country', 'colors', 'symbols', 'design_complexity', 'readability', 'public_opinion'])
Getting all the values:
Values: dict_values(['Confusistan', ['red', 'green', 'purple', 'neon yellow'], ['star', 'dragon', 'rainbow', "text: 'Unity'"], 'Extremely High', 'Unreadable', 'Negative'])
Limitations on Keys and Values#
Philadelphia Flag#
Syntax
Key Limitations
Keys must be unique. If a key is duplicated, the last value assigned to it will overwrite earlier values.
Keys must be immutable types: Examples include strings, numbers, and tuples. Mutable types (e.g., lists, sets) cannot be used as keys.
Examples:
Valid keys:
"name"
,42
,(1, 2)
Invalid keys:
[1, 2, 3]
,{ "key": "value" }
Syntax
Value Limitations
Values can be any type, but their mutability affects how the dictionary behaves.
Nested mutable types (e.g., lists or dictionaries) can cause unintentional side effects if modified directly.
Examples:
Valid values:
"string"
,[1, 2, 3]
,{ "nested": "dict" }
Caution with mutable values: Modifying
bad_flag["colors"]
affects the dictionary directly.
try:
invalid_key_dict = {[1, 2, 3]: "Invalid"}
except TypeError as e:
print("\nExample of Invalid Key Error:", e)
Nested Dictionaries#
You can nest dictionaries within dictionaries to create more complex data structures. This is useful for representing hierarchical relationships or structured data. This is done by assigning a dictionary as a value to a key in another dictionary.
Note
Nested dictionaries are the foundation of JSON (JavaScript Object Notation), a popular data interchange format. Nearly everything on the web is transmitted as JSON, including API responses, configuration files, and more. Even this courses grades are stored in a JSON and transmitted via JSON.
nested_dict = {"flag_details": bad_flag}
nested_dict["flag_details"]["colors"].append("gold")
print("\nModified Nested Dictionary (caution with mutable values):")
print(nested_dict)
Modified Nested Dictionary (caution with mutable values):
{'flag_details': {'country': 'Confusistan', 'colors': ['red', 'green', 'purple', 'neon yellow', 'gold'], 'symbols': ['star', 'dragon', 'rainbow', "text: 'Unity'"], 'design_complexity': 'Extremely High', 'readability': 'Unreadable', 'public_opinion': 'Negative'}}
Advantages of Dictionaries#
Fast lookups: Average time complexity is \(O(1)\).
Flexible: Can store structured, nested data.
Dynamic: Keys and values can be added or removed on the fly.
Efficient: Memory-efficient for large datasets.
Limitations of Dictionaries#
Keys must be unique and immutable.
Higher memory usage: Requires more memory compared to other data structures like lists.
Unordered in older Python versions: Dictionaries do not maintain order prior to Python 3.7.
Practical Example: Evaluating Flags#
flag_evaluation = {
"Confusistan": {"colors": 10, "symbols": 5, "readability": 1},
"Rainbowland": {"colors": 7, "symbols": 3, "readability": 5},
"Clashopolis": {"colors": 2, "symbols": 1, "readability": 9},
}
print("\nFlag Evaluation Scores:")
# we will learn about using dictionary with for loops later in the course.
for flag, scores in flag_evaluation.items():
complexity_score = sum(scores.values())
print(f"{flag} total score: {complexity_score}")
Flag Evaluation Scores:
Confusistan total score: 16
Rainbowland total score: 15
Clashopolis total score: 12
๐
Digression: My favorite flag is the Chicago flag. Itโs simple, meaningful, and iconic. Itโs a great example of good flag design. Now not only are you a Python Dictionary expert, but you also are a budding vexillologist!