def unstack(
        self,
        dim: Dims = None,
        *,
        fill_value: Any = xrdtypes.NA,
        sparse: bool = False,
    ) -> Self:
        """
        Unstack existing dimensions corresponding to MultiIndexes into
        multiple new dimensions.

        New dimensions will be added at the end.

        Parameters
        ----------
        dim : str, Iterable of Hashable or None, optional
            Dimension(s) over which to unstack. By default unstacks all
            MultiIndexes.
        fill_value : scalar or dict-like, default: nan
            value to be filled. If a dict-like, maps variable names to
            fill values. If not provided or if the dict-like does not
            contain all variables, the dtype's NA value will be used.
        sparse : bool, default: False
            use sparse-array if True

        Returns
        -------
        unstacked : Dataset
            Dataset with unstacked data.

        See Also
        --------
        Dataset.stack
        """

        if dim is None:
            dims = list(self.dims)
        else:
            if isinstance(dim, str) or not isinstance(dim, Iterable):
                dims = [dim]
            else:
                dims = list(dim)

            missing_dims = set(dims) - set(self.dims)
            if missing_dims:
                raise ValueError(
                    f"Dimensions {tuple(missing_dims)} not found in data dimensions {tuple(self.dims)}"
                )

        # each specified dimension must have exactly one multi-index
        stacked_indexes: dict[Any, tuple[Index, dict[Hashable, Variable]]] = {}
        for d in dims:
            idx, idx_vars = self._get_stack_index(d, multi=True)
            if idx is not None:
                stacked_indexes[d] = idx, idx_vars

        if dim is None:
            dims = list(stacked_indexes)
        else:
            non_multi_dims = set(dims) - set(stacked_indexes)
            if non_multi_dims:
                raise ValueError(
                    "cannot unstack dimensions that do not "
                    f"have exactly one multi-index: {tuple(non_multi_dims)}"
                )

        result = self.copy(deep=False)

        # we want to avoid allocating an object-dtype ndarray for a MultiIndex,
        # so we can't just access self.variables[v].data for every variable.
        # We only check the non-index variables.
        # https://github.com/pydata/xarray/issues/5902
        nonindexes = [
            self.variables[k] for k in set(self.variables) - set(self._indexes)
        ]
        # Notes for each of these cases:
        # 1. Dask arrays don't support assignment by index, which the fast unstack
        #    function requires.
        #    https://github.com/pydata/xarray/pull/4746#issuecomment-753282125
        # 2. Sparse doesn't currently support (though we could special-case it)
        #    https://github.com/pydata/sparse/issues/422
        # 3. pint requires checking if it's a NumPy array until
        #    https://github.com/pydata/xarray/pull/4751 is resolved,
        #    Once that is resolved, explicitly exclude pint arrays.
        #    pint doesn't implement `np.full_like` in a way that's
        #    currently compatible.
        sparse_array_type = array_type("sparse")
        needs_full_reindex = any(
            is_duck_dask_array(v.data)
            or isinstance(v.data, sparse_array_type)
            or not isinstance(v.data, np.ndarray)
            for v in nonindexes
        )

        for d in dims:
            if needs_full_reindex:
                result = result._unstack_full_reindex(
                    d, stacked_indexes[d], fill_value, sparse
                )
            else:
                result = result._unstack_once(d, stacked_indexes[d], fill_value, sparse)
        return result

        Unstack existing dimensions corresponding to MultiIndexes into
        multiple new dimensions.

        New dimensions will be added at the end.

        Parameters
        ----------
        dim : str, Iterable of Hashable or None, optional
            Dimension(s) over which to unstack. By default unstacks all
            MultiIndexes.
        fill_value : scalar or dict-like, default: nan
            value to be filled. If a dict-like, maps variable names to
            fill values. If not provided or if the dict-like does not
            contain all variables, the dtype's NA value will be used.
        sparse : bool, default: False
            use sparse-array if True

        Returns
        -------
        unstacked : Dataset
            Dataset with unstacked data.

        See Also
        --------
        Dataset.stack
        
xarray/core/dataset.py