code: def delete(self, deletion_point, no_to_delete, axis, tab=None):
          
  
          if not 0 <= axis < len(self.shape):
              raise ValueError("Axis not in grid dimensions")
  
          if no_to_delete < 0:
              raise ValueError("Cannot delete negative number of rows/cols/...")
  
          elif no_to_delete >= self.shape[axis]:
              raise ValueError("Last row/column/table must not be deleted")
  
          if deletion_point > self.shape[axis] or \
             deletion_point <= -self.shape[axis]:
              raise IndexError("Deletion point not in grid")
  
          new_keys = {}
          del_keys = []
  
          # Note that the loop goes over a list that copies all dict keys
          for key in self.dict_grid.keys():
              if tab is None or tab == key[2]:
                  if deletion_point <= key[axis] < deletion_point + no_to_delete:
                      del_keys.append(key)
  
                  elif key[axis] >= deletion_point + no_to_delete:
                      new_key = list(key)
                      new_key[axis] -= no_to_delete
  
                      new_keys[tuple(new_key)] = self(key)
                      del_keys.append(key)
  
          # Now re-insert moved keys
  
          for key in new_keys:
              self.__setitem__(key, new_keys[key])
  
          for key in del_keys:
              if key not in new_keys and self(key) is not None:
                  self.pop(key)
  
          self._adjust_rowcol(deletion_point, -no_to_delete, axis, tab=tab)
          self._adjust_cell_attributes(deletion_point, -no_to_delete, axis)
docs: Deletes no_to_delete rows/cols/... starting with deletion_point
  
          Axis specifies number of dimension, i.e. 0 == row, 1 == col, 2 == tab