Course Content
Python Indentation, Comments and Variables
0/2
Object Oriented Programming in Python
0/1
Exception Handling in Python
0/1
Sending emails with Python
0/1
Unit test in python programming
0/1
Python programming (zero to advance!!!)
About Lesson

“COLLECTIONS” MODULE IN PYTHON 

The `collections` module in Python provides specialized container datatypes beyond the built-in data types like lists, tuples, dictionaries, and sets. It includes several classes that extend the capabilities of these built-in types for specific use cases. Some of the notable classes in the `collections` module include:

1. `Counter`: A subclass of dictionary that counts hashable objects. It is useful for counting occurrences of items in iterable objects like lists.

Below is a code example demonstrating the usage of `Counter` from the `collections` module:

“`python
from collections import Counter

# Create a list of elements
elements = [‘apple’, ‘banana’, ‘apple’, ‘orange’, ‘banana’, ‘apple’]

# Use Counter to count occurrences of elements in the list
element_counter = Counter(elements)

# Print the Counter object
print(“Counter object:”, element_counter)

# Access the count of specific elements
print(“Count of ‘apple’:”, element_counter[‘apple’])
print(“Count of ‘banana’:”, element_counter[‘banana’])
print(“Count of ‘orange’:”, element_counter[‘orange’])

# Access elements and their counts as a dictionary
print(“Element counts as dictionary:”, element_counter.items())

# Convert Counter object to a dictionary
element_dict = dict(element_counter)
print(“Counter converted to dictionary:”, element_dict)
“`

Output:
“`
Counter object: Counter({‘apple’: 3, ‘banana’: 2, ‘orange’: 1})
Count of ‘apple’: 3
Count of ‘banana’: 2
Count of ‘orange’: 1
Element counts as dictionary: dict_items([(‘apple’, 3), (‘banana’, 2), (‘orange’, 1)])
Counter converted to dictionary: {‘apple’: 3, ‘banana’: 2, ‘orange’: 1}
“`

In this example, we first create a list of elements. We then use the `Counter` class to count the occurrences of each element in the list. The `Counter` object stores the counts as key-value pairs, where the keys are the elements and the values are their counts. We can access the count of specific elements using dictionary-like syntax (`element_counter[‘element’]`).

The `Counter` object also provides methods to access elements and their counts as dictionaries, and it can be converted to a regular dictionary using the `dict()` constructor.

2. `deque`: A double-ended queue implementation that allows efficient appends and pops from either end of the queue. It is useful for implementing queues and stacks.

 

Below is a code example demonstrating the usage of `deque` from the `collections` module:

“`python
from collections import deque

# Create a deque
my_deque = deque([‘apple’, ‘banana’, ‘cherry’])

# Append elements to the right end of the deque
my_deque.append(‘orange’)
my_deque.append(‘grape’)

# Append elements to the left end of the deque
my_deque.appendleft(‘watermelon’)
my_deque.appendleft(‘kiwi’)

# Print the deque
print(“Deque:”, my_deque)

# Pop elements from the right end of the deque
popped_right = my_deque.pop()
print(“Popped from the right end:”, popped_right)

# Pop elements from the left end of the deque
popped_left = my_deque.popleft()
print(“Popped from the left end:”, popped_left)

# Print the modified deque
print(“Modified Deque:”, my_deque)
“`

Output:
“`
Deque: deque([‘kiwi’, ‘watermelon’, ‘apple’, ‘banana’, ‘cherry’, ‘orange’, ‘grape’])
Popped from the right end: grape
Popped from the left end: kiwi
Modified Deque: deque([‘watermelon’, ‘apple’, ‘banana’, ‘cherry’, ‘orange’])
“`

In this example, we first create a deque named `my_deque` with some initial elements. We then append elements to both ends of the deque using the `append()` and `appendleft()` methods. After modifying the deque, we use the `pop()` and `popleft()` methods to remove elements from the right and left ends of the deque, respectively. Finally, we print the modified deque to observe the changes.

3. `namedtuple`: A factory function for creating tuple subclasses with named fields. It provides a convenient way to create immutable objects with named attributes.

 

Below is an example demonstrating the usage of `namedtuple`:

“`python
from collections import namedtuple

# Define a namedtuple for representing a Point
Point = namedtuple(‘Point’, [‘x’, ‘y’])

# Create a Point instance
p1 = Point(1, 2)

# Access elements by name
print(“x coordinate:”, p1.x)
print(“y coordinate:”, p1.y)

# Access elements by index
print(“Accessing by index:”, p1[0], p1[1])

# Unpack the namedtuple
x, y = p1
print(“Unpacked values:”, x, y)
“`

Output:
“`
x coordinate: 1
y coordinate: 2
Accessing by index: 1 2
Unpacked values: 1 2
“`

In this example, we define a namedtuple `Point` with fields `x` and `y` using the `namedtuple` function. We create an instance `p1` of the `Point` namedtuple by passing values for `x` and `y`. We can access the elements of the namedtuple both by name (`p1.x` and `p1.y`) and by index (`p1[0]` and `p1[1]`). Additionally, we can also unpack the namedtuple into separate variables `x` and `y`.

4. `OrderedDict`:

`OrderedDict` is a dictionary subclass available in the `collections` module of Python. It retains the order of items as they were inserted, unlike the regular dictionary which does not guarantee any specific order of keys.

Below is how `OrderedDict` differs from the standard dictionary:

1. Order Preservation:
– When you iterate over an `OrderedDict`, the items will be returned in the order they were inserted.
– This feature is particularly useful when you want to maintain the order of insertion or define a specific order for your dictionary keys.

2. Equality Testing:
– In Python 3.7 and later, regular dictionaries preserve the order of insertion. However, prior to Python 3.7, the standard dictionary did not guarantee order preservation.
– `OrderedDict` ensures that the equality test between two dictionaries considers not just their contents but also the order of insertion.

Here’s an example illustrating the usage of `OrderedDict`:

“`python
from collections import OrderedDict

# Create an OrderedDict with some key-value pairs
ordered_dict = OrderedDict([(‘a’, 1), (‘b’, 2), (‘c’, 3)])

# Add a new key-value pair
ordered_dict[‘d’] = 4

# Iterate over the OrderedDict
print(“OrderedDict contents:”)
for key, value in ordered_dict.items():
print(key, value)
“`

Output:
“`
OrderedDict contents:
a 1
b 2
c 3
d 4
“`

In this example, the order of key-value pairs is preserved in the `OrderedDict` as they were inserted. When we iterate over the `OrderedDict`, the items are returned in the order of insertion.

5. `defaultdict`:

`defaultdict` is a specialized dictionary implementation available in the Python `collections` module. It is a subclass of the built-in dictionary (`dict`) type and provides an additional feature over regular dictionaries: the ability to specify a default value factory for missing keys.

Here’s how `defaultdict` differs from the standard dictionary:

1. Default Values:
– When you access a key that does not exist in a regular dictionary, it raises a `KeyError` exception. However, in a `defaultdict`, if you attempt to access a missing key, it returns a default value determined by a factory function that you specify.
– This eliminates the need to manually check whether a key exists before accessing it, which can simplify code and make it more readable.

Here’s an example illustrating the usage of `defaultdict`:

“`python
from collections import defaultdict

# Define a defaultdict with int as the default value factory
num_dict = defaultdict(int)

# Increment the count for each character in the string
word = “hello”
for char in word:
num_dict[char] += 1

print(num_dict) # Output: defaultdict(<class ‘int’>, {‘h’: 1, ‘e’: 1, ‘l’: 2, ‘o’: 1})
“`

In this example, when we access a missing key in `num_dict`, it automatically creates the key with the default value of `int`, which is `0`. Then, we increment the count for each character encountered in the string.

`defaultdict` is particularly useful for tasks involving counting, grouping, or initializing nested data structures without having to handle missing keys manually. It simplifies code and makes it more concise and readable.

6. `ChainMap`: A class that allows multiple dictionaries to be logically chained together as a single mapping. It is useful for treating multiple dictionaries as a single unit.

 

`ChainMap` is a class in the Python `collections` module that provides the ability to link multiple dictionaries or mappings together into a single view. It encapsulates a list of dictionaries and allows you to search them as a single mapping.

Here are the key characteristics and functionalities of `ChainMap`:

1. Combining Multiple Dictionaries:
– `ChainMap` combines multiple dictionaries or mappings into a single, logically linked view.
– It preserves the original dictionaries and their contents; it does not create a new merged dictionary.

2. Search Order:
– When you query a key in a `ChainMap`, it searches the underlying dictionaries in the order they were added.
– It returns the value associated with the first occurrence of the key found in the underlying mappings.
– If the key is not found in any of the dictionaries, it raises a `KeyError`.

3. Mutability:
– `ChainMap` itself is immutable; you cannot modify its contents directly.
– However, you can modify the underlying dictionaries, and these changes will be reflected in the `ChainMap` view.

4. Use Cases:
– `ChainMap` is useful for managing configurations, settings, or namespaces where you have a hierarchy of dictionaries representing different levels of scope or priority.
– It simplifies the process of searching for values across multiple dictionaries without having to manually iterate over each dictionary.

Here’s a basic example demonstrating the usage of `ChainMap`:

“`python
from collections import ChainMap

# Define two dictionaries
dict1 = {‘a’: 1, ‘b’: 2}
dict2 = {‘b’: 3, ‘c’: 4}

# Create a ChainMap with the dictionaries
chain_map = ChainMap(dict1, dict2)

# Accessing keys
print(chain_map[‘a’]) # Output: 1
print(chain_map[‘b’]) # Output: 2 (from dict1, as it’s found first)
print(chain_map[‘c’]) # Output: 4

# Adding a new key-value pair
dict3 = {‘d’: 5}
chain_map = chain_map.new_child(dict3)
print(chain_map[‘d’]) # Output: 5
“`

In this example, we create a `ChainMap` from two dictionaries, `dict1` and `dict2`. We access keys and observe that the value associated with `’b’` comes from `dict1`. Finally, we add a new dictionary `dict3` to the `ChainMap` using the `new_child()` method and access its key `’d’`.

7. 

`UserDict`, `UserList`, and `UserString` are wrapper classes provided by the Python `collections` module. They are designed to allow user-defined objects to be subclassed easily, providing a convenient way to create custom container types.

Here’s a brief overview of each:

1. UserDict:
– `UserDict` is a subclass of `dict` that acts as a wrapper around dictionary objects.
– It provides a convenient way to create dictionary-like objects with custom behavior by subclassing `UserDict` and overriding its methods.
– It is particularly useful when you need to customize the behavior of dictionaries without directly subclassing the built-in `dict` class.

2. UserList:
– `UserList` is a subclass of `list` that acts as a wrapper around list objects.
– Similar to `UserDict`, it provides a convenient way to create list-like objects with custom behavior by subclassing `UserList` and overriding its methods.
– It allows you to define custom behavior for list operations such as appending, extending, or removing elements.

3. UserString:
– `UserString` is a subclass of `str` that acts as a wrapper around string objects.
– It provides a convenient way to create string-like objects with custom behavior by subclassing `UserString` and overriding its methods.
– You can use `UserString` to define custom string manipulation methods or enforce specific string formatting rules.

These wrapper classes are particularly useful when you need to extend the behavior of built-in container types (`dict`, `list`, `str`) without directly modifying their implementations. By subclassing `UserDict`, `UserList`, or `UserString`, you can encapsulate custom logic and ensure better code organization and maintainability.

Here’s a simple example demonstrating the usage of `UserDict`:

“`python
from collections import UserDict

# Custom dictionary subclass
class MyDict(UserDict):
def __getitem__(self, key):
print(f”Getting item for key: {key}”)
return super().__getitem__(key)

# Creating an instance of the custom dictionary
my_dict = MyDict({‘a’: 1, ‘b’: 2})

# Accessing items
print(my_dict[‘a’]) # Output: Getting item for key: a; 1
“`

In this example, `MyDict` is a subclass of `UserDict`, and it overrides the `__getitem__()` method to print a message when an item is accessed. The custom behavior is encapsulated within the `MyDict` class, allowing for better code organization and reuse.

 

 

The `collections` module provides efficient and convenient data structures for various common programming tasks. By leveraging these classes, you can write more efficient and readable code for handling complex data structures and algorithms.

 

EXERCISES

1. Create a Dictionary:
Create a dictionary representing a person with keys such as name, age, gender, and city.

2. Update Dictionary:
Update the age of the person in the dictionary created above.

3. Access Dictionary Values:
Print the name and city of the person from the dictionary.

4. Add Key-Value Pair:
Add a new key-value pair representing the person’s occupation to the dictionary.

5. Remove Key-Value Pair:
Remove the city key-value pair from the dictionary.

6. Iterate Over Dictionary:
Iterate over the dictionary and print all key-value pairs.

7. Check if Key Exists:
Check if the key “gender” exists in the dictionary.

8. Get Value with Default:
Get the value for the key “age”, if it doesn’t exist, return “Not Available”.

9. Merge Dictionaries:
Create another dictionary representing additional information about the person and merge it with the existing dictionary.

10. Clear Dictionary:
Clear all the elements from the dictionary.

These exercises will help you get familiar with dictionary operations and manipulation in Python.

Join the conversation