parameters: (self, position)
docstring: removes specified node from doubly linked list and returns data.
              raise exception, if position is invalid.
docstring_summary: removes specified node from doubly linked list and returns data.
              raise exception, if position is invalid.
docstring_tokens: removes specified node from doubly linked list and returns data . raise exception if position is invalid .
function: def delete_at(self, position):
          """ removes specified node from doubly linked list and returns data.
              raise exception, if position is invalid.
          """
          dll_size = len(self)
          if position < 0 or position > dll_size:
              raise Exception("Invalid position")
  
          if position == 0:
              self.delete_head()
          elif position == dll_size:
              self.delete_tail()
          else:
              current = self.head
              for _ in range(0, position):
                  current = current.next
  
              previous_node = current.previous
              next_node = current.next
              previous_node.next = next_node
              next_node.previous = previous_node
              del current
function_tokens: def delete_at ( self , position ) : dll_size = len ( self ) if position < 0 or position > dll_size : raise Exception ( "Invalid position" ) if position == 0 : self . delete_head ( ) elif position == dll_size : self . delete_tail ( ) else : current = self . head for _ in range ( 0 , position ) : current = current . next previous_node = current . previous next_node = current . next previous_node . next = next_node next_node . previous = previous_node del current