Hone logo
Hone
Problems

Generic Data Structure: A Customizable Container

In Python, we often work with collections of data. While standard Python lists and dictionaries are versatile, sometimes you need a specialized container that enforces certain types of elements or has specific behavior. This challenge asks you to create a generic container class that can hold elements of a specified type, enhancing type safety and predictable behavior.

Problem Description

Your task is to implement a generic TypedContainer class in Python. This class should be able to store elements, but crucially, it should only allow elements of a specific, pre-defined type. When the container is initialized, you should specify the type of elements it will hold. Any attempt to add an element of a different type should raise a TypeError.

Key Requirements:

  1. Generic Type Specification: The TypedContainer should accept a type hint during initialization (e.g., int, str, list).
  2. Element Addition: Implement a method (e.g., add or append) to add elements to the container. This method must check if the type of the element being added matches the container's specified type.
  3. Type Enforcement: If an element of an incorrect type is added, raise a TypeError with a descriptive message.
  4. Element Retrieval: Provide a way to access the stored elements (e.g., by making the container iterable or providing a get_all method).
  5. Container Behavior: The container should behave like a list in terms of storing multiple elements in order.

Expected Behavior:

  • A TypedContainer initialized for int should only accept integers.
  • A TypedContainer initialized for str should only accept strings.
  • Attempts to add non-matching types should result in a TypeError.

Edge Cases:

  • What happens if you try to initialize the container with a non-type object? (e.g., an integer value instead of int). This should ideally be handled, perhaps by raising a TypeError or ValueError.
  • Consider the case of None. Should None be allowed if the specified type is Optional[SomeType]? For this challenge, assume None is only allowed if the specified type is NoneType itself, or if it's explicitly allowed by a mechanism not covered here (i.e., focus on exact type matching for now).

Examples

Example 1:

# Initialize a container for integers
int_container = TypedContainer(int)

# Add valid integers
int_container.add(10)
int_container.add(25)

# Attempt to add a string
try:
    int_container.add("hello")
except TypeError as e:
    print(e)

# Retrieve elements
print(list(int_container))

Output:

Cannot add 'hello' (str) to a container expecting <class 'int'>.
[10, 25]

Explanation: The TypedContainer was initialized to hold int. When "hello" (a str) was added, a TypeError was raised. The valid integers were stored and can be retrieved.

Example 2:

# Initialize a container for strings
string_container = TypedContainer(str)

# Add valid strings
string_container.add("apple")
string_container.add("banana")

# Attempt to add a float
try:
    string_container.add(3.14)
except TypeError as e:
    print(e)

# Retrieve elements
print(list(string_container))

Output:

Cannot add 3.14 (<class 'float'>) to a container expecting <class 'str'>.
['apple', 'banana']

Explanation: Similar to Example 1, but for strings. A float was rejected.

Example 3: Initialization Error

# Attempt to initialize with a non-type value
try:
    invalid_container = TypedContainer(123)
except TypeError as e:
    print(e)

Output:

Expected a type for the container, but received <class 'int'>.

Explanation: The constructor expects a type object (like int or str), not an instance of a type. This input caused a TypeError during initialization.

Constraints

  • The TypedContainer class must be implemented using standard Python features.
  • The element storage should maintain insertion order, similar to a list.
  • The add method should have a time complexity of O(1) on average (excluding the type check, which is typically O(1)).
  • The TypedContainer should be iterable.

Notes

  • Consider using isinstance() for type checking.
  • The __init__ method is where you should store the expected type.
  • The add method is where the core type enforcement logic will reside.
  • Making your class iterable (e.g., by implementing __iter__) is a good way to allow easy retrieval of elements.
  • Think about how you can provide a clear and informative error message when a type mismatch occurs.
Loading editor...
python