input: Write a function that implements a hash table in Python with the following methods: insert, delete, and retrieve. The hash table should handle potential hash collisions by using separate chaining. Provide the class definition and its methods, followed by a set of assertion tests to ensure the methods work as expected.
  assert insert("key1", "value1")
  assert retrieve("key1") == "value1"
  assert insert("key1", "new_value1")
  assert retrieve("key1") == "new_value1"
  assert delete("key1")
  assert retrieve("key1") is None
  assert insert("key2", "value2")
  assert retrieve("key2") == "value2"
output: class HashTable:
      def __init__(self, size=10):
          self.size = size
          self.table = [[] for _ in range(self.size)]
  
      def _hash(self, key):
          return hash(key) % self.size
  
      def insert(self, key, value):
          index = self._hash(key)
          for i, (k, v) in enumerate(self.table[index]):
              if k == key:
                  self.table[index][i] = (key, value)
                  return True
          self.table[index].append((key, value))
          return True
  
      def retrieve(self, key):
          index = self._hash(key)
          for k, v in self.table[index]:
              if k == key:
                  return v
          return None
  
      def delete(self, key):
          index = self._hash(key)
          for i, (k, v) in enumerate(self.table[index]):
              if k == key:
                  del self.table[index][i]
                  return True
          return False