Dictionary in Python
A dictionary in Python is a built-in data type that stores collections of key-value pairs.
Dictionaries are also known as associative arrays or hash maps. They are unordered, mutable,
and indexed by keys, which can be of any immutable data type (such as strings, numbers, or
tuples).
Creating a Dictionary
Dictionaries can be created in several ways:
   1. Using curly braces {}:
       my_dict = {"key1": "value1", "key2": "value2"}
   2. Using the dict() constructor:
       my_dict = dict(key1="value1", key2="value2")
   3. Using a list of tuples:
       my_dict = dict([("key1", "value1"), ("key2", "value2")])
Accessing Values
You can access values by using their corresponding keys:
value = my_dict["key1"]
If you try to access a key that does not exist, a KeyError will be raised. To avoid this, use the
get() method, which returns None or a default value if the key is not found:
value = my_dict.get("key1", "default_value")
Adding or Modifying Entries
You can add a new key-value pair or modify an existing one by using the assignment
operator:
my_dict["key3"] = "value3" # Adds a new key-value pair
my_dict["key1"] = "new_value" # Modifies an existing key-value pair
Removing Entries
There are several methods to remove items from a dictionary:
   1. Using the del statement:
       del my_dict["key1"]
   2. Using the pop() method, which returns the removed value:
       value = my_dict.pop("key2")
   3. Using the popitem() method to remove and return an arbitrary key-value pair
      (in Python 3.7+ it removes the last item):
       key, value = my_dict.popitem()
   4. Using the clear() method to remove all items:
       my_dict.clear()
Dictionary Methods
Python dictionaries come with various useful methods:
      keys():   Returns a view object of all keys.
       keys = my_dict.keys()
      values():   Returns a view object of all values.
       values = my_dict.values()
      items():   Returns a view object of all key-value pairs.
       items = my_dict.items()
      update():   Updates the dictionary with key-value pairs from another dictionary or an
       iterable of key-value pairs.
       my_dict.update({"key4": "value4"})
Dictionary Comprehensions
Similar to list comprehensions, you can create dictionaries using dictionary comprehensions:
python
squares = {x: x*x for x in range(6)}
Nested Dictionaries
Dictionaries can contain other dictionaries, which allows you to create nested structures:
nested_dict = {"first": {"a": 1, "b": 2}, "second": {"c": 3, "d": 4}}
Iterating Through Dictionaries
You can iterate through dictionaries using loops:
for key in my_dict:
    print(key, my_dict[key])
# or
for key, value in my_dict.items():
    print(key, value)
Common Use Cases
        Lookup tables: Efficiently find a value associated with a unique key.
        Data storage: Store related pieces of data together, using descriptive keys.
        Counting occurrences: Track how many times something appears in a collection.
# Creating a simple dictionary
fruit_colors = {
    "apple": "red",
    "banana": "yellow",
    "cherry": "red",
    "grape": "purple"
print("Initial dictionary:")
print("fruit_colors:", fruit_colors)
# Accessing values
print("\nAccessing values:")
print("Color of apple:", fruit_colors["apple"])
print("Color of banana:", fruit_colors.get("banana"))
print("Color of orange (with default):", fruit_colors.get("orange", "unknown"))
# Adding or modifying entries
fruit_colors["orange"] = "orange" # Adding a new key-value pair
fruit_colors["banana"] = "green" # Modifying an existing key-value pair
print("\nAfter adding and modifying entries:")
print("fruit_colors:", fruit_colors)
# Removing entries
del fruit_colors["cherry"] # Using del to remove an entry
print("\nAfter deleting 'cherry':")
print("fruit_colors:", fruit_colors)
removed_color = fruit_colors.pop("grape") # Using pop() to remove an entry
print("\nAfter popping 'grape':", removed_color)
print("fruit_colors:", fruit_colors)
fruit_colors.clear() # Using clear() to remove all entries
print("\nAfter clearing the dictionary:")
print("fruit_colors:", fruit_colors)
# Dictionary methods
fruit_colors = {"apple": "red", "banana": "yellow", "cherry": "red"}
print("\nDictionary methods:")
print("Keys:", fruit_colors.keys())
print("Values:", fruit_colors.values())
print("Items:", fruit_colors.items())
# Updating a dictionary
fruit_colors.update({"grape": "purple", "orange": "orange"})
print("\nAfter updating the dictionary:")
print("fruit_colors:", fruit_colors)
# Dictionary comprehension
fruit_lengths = {fruit: len(fruit) for fruit in fruit_colors}
print("\nDictionary comprehension (fruit lengths):")
print("fruit_lengths:", fruit_lengths)
# Nested dictionaries
fruit_properties = {
    "apple": {"color": "red", "taste": "sweet"},
    "banana": {"color": "yellow", "taste": "sweet"},
    "grape": {"color": "purple", "taste": "sweet or sour"}
print("\nNested dictionary:")
print("fruit_properties:", fruit_properties)
# Iterating through dictionaries
print("\nIterating through fruit_colors:")
for fruit in fruit_colors:
    print(f"Fruit: {fruit}, Color: {fruit_colors[fruit]}")
print("\nIterating through fruit_colors using items():")
for fruit, color in fruit_colors.items():
    print(f"Fruit: {fruit}, Color: {color}")
# Common use cases
# Counting occurrences
fruit_basket = ["apple", "banana", "apple", "cherry", "banana", "banana"]
fruit_count = {}
for fruit in fruit_basket:
    if fruit in fruit_count:
      fruit_count[fruit] += 1
    else:
      fruit_count[fruit] = 1
print("\nCounting occurrences in the fruit basket:")
print("fruit_count:", fruit_count)
Output:
Initial dictionary:
fruit_colors: {'apple': 'red', 'banana': 'yellow', 'cherry': 'red', 'grape': 'purple'}
Accessing values:
Color of apple: red
Color of banana: yellow
Color of cherry (with default): red
After adding and modifying entries:
fruit_colors: {'apple': 'red', 'banana': 'green', 'cherry': 'red', 'grape': 'purple', 'orange':
'orange'}
After deleting 'cherry':
fruit_colors: {'apple': 'red', 'banana': 'green', 'grape': 'purple', 'orange': 'orange'}
After popping 'grape': purple
fruit_colors: {'apple': 'red', 'banana': 'green', 'orange': 'orange'}
After clearing the dictionary:
fruit_colors: {}
Dictionary methods:
Keys: dict_keys(['apple', 'banana', 'cherry'])
Values: dict_values(['red', 'yellow', 'red'])
Items: dict_items([('apple', 'red'), ('banana', 'yellow'), ('cherry', 'red')])
After updating the dictionary:
fruit_colors: {'apple': 'red', 'banana': 'yellow', 'cherry': 'red', 'grape': 'purple', 'orange':
'orange'}
Dictionary comprehension (fruit lengths):
fruit_lengths: {'apple': 5, 'banana': 6, 'cherry': 6, 'grape': 5, 'orange': 6}
Nested dictionary:
fruit_properties: {'apple': {'color': 'red', 'taste': 'sweet'}, 'banana': {'color': 'yellow', 'taste':
'sweet'}, 'grape': {'color': 'purple', 'taste': 'sweet or sour'}}
Iterating through fruit_colors:
Fruit: apple, Color: red
Fruit: banana, Color: yellow
Fruit: cherry, Color: red
Fruit: grape, Color: purple
Fruit: orange, Color: orange
Iterating through fruit_colors using items():
Fruit: apple, Color: red
Fruit: banana, Color: yellow
Fruit: cherry, Color: red
Fruit: grape, Color: purple
Fruit: orange, Color: orange
Counting occurrences in the fruit basket:
fruit_count: {'apple': 2, 'banana': 3, 'cherry': 1}