input: Write a function to create a doubly linked list in Python that allows for the insertion of elements at both the end and the beginning, and also supports reversing the list. The function should return the modified list after each operation.
  
  
  class Node:
      def __init__(self, data):
          self.data = data
          self.next = None
          self.prev = None
  
  class DoubleLinkedList:
      def __init__(self):
          self.head = None
   
      def append(self, new_data):
          new_node = Node(new_data)
          if self.head is None:
              self.head =  new_node
          else:
              curr_node = self.head
              while curr_node.next != None:
                  curr_node = curr_node.next
              curr_node.next = new_node
              new_node.prev = curr_node
   
      def prepend(self, new_data):
          new_node = Node(new_data)
          if self.head is None:
              self.head = new_node
              return
          new_node.next = self.head
          self.head.prev = new_node
          self.head = new_node
  
      def reverse(self):
          curr_node = self.head
          while curr_node:
              temp = curr_node.next
              curr_node.next = curr_node.prev
              curr_node.prev = temp
              curr_node = curr_node.prev
          if temp:
              self.head = temp.prev
  
  assert isinstance(DoubleLinkedList, type)
  assert callable(DoubleLinkedList().append)
  assert callable(DoubleLinkedList().prepend)
  assert callable(DoubleLinkedList().reverse)
  dll = DoubleLinkedList()
  dll.append(1)
  dll.append(2)
  dll.prepend(0)
  dll.reverse()
  assert dll.head.data == 2
  assert dll.head.next.data == 1
  assert dll.head.next.next.data == 0
  
output: 
  class Node:
      def __init__(self, data):
          self.data = data
          self.next = None
          self.prev = None
  
  class DoubleLinkedList:
      def __init__(self):
          self.head = None
   
      def append(self, new_data):
          new_node = Node(new_data)
          if self.head is None:
              self.head =  new_node
          else:
              curr_node = self.head
              while curr_node.next != None:
                  curr_node = curr_node.next
              curr_node.next = new_node
              new_node.prev = curr_node
   
      def prepend(self, new_data):
          new_node = Node(new_data)
          if self.head is None:
              self.head = new_node
              return
          new_node.next = self.head
          self.head.prev = new_node
          self.head = new_node
  
      def reverse(self):
          curr_node = self.head
          while curr_node:
              temp = curr_node.next
              curr_node.next = curr_node.prev
              curr_node.prev = temp
              curr_node = curr_node.prev
          if temp:
              self.head = temp.prev
  