def diff(
        self,
        dim: Hashable,
        n: int = 1,
        *,
        label: Literal["upper", "lower"] = "upper",
    ) -> Self:
        """Calculate the n-th order discrete difference along given axis.

        Parameters
        ----------
        dim : Hashable
            Dimension over which to calculate the finite difference.
        n : int, default: 1
            The number of times values are differenced.
        label : {"upper", "lower"}, default: "upper"
            The new coordinate in dimension ``dim`` will have the
            values of either the minuend's or subtrahend's coordinate
            for values 'upper' and 'lower', respectively.

        Returns
        -------
        difference : Dataset
            The n-th order finite difference of this object.

        Notes
        -----
        `n` matches numpy's behavior and is different from pandas' first argument named
        `periods`.

        Examples
        --------
        >>> ds = xr.Dataset({"foo": ("x", [5, 5, 6, 6])})
        >>> ds.diff("x")
        <xarray.Dataset> Size: 24B
        Dimensions:  (x: 3)
        Dimensions without coordinates: x
        Data variables:
            foo      (x) int64 24B 0 1 0
        >>> ds.diff("x", 2)
        <xarray.Dataset> Size: 16B
        Dimensions:  (x: 2)
        Dimensions without coordinates: x
        Data variables:
            foo      (x) int64 16B 1 -1

        See Also
        --------
        Dataset.differentiate
        """
        if n == 0:
            return self
        if n < 0:
            raise ValueError(f"order `n` must be non-negative but got {n}")

        # prepare slices
        slice_start = {dim: slice(None, -1)}
        slice_end = {dim: slice(1, None)}

        # prepare new coordinate
        if label == "upper":
            slice_new = slice_end
        elif label == "lower":
            slice_new = slice_start
        else:
            raise ValueError("The 'label' argument has to be either 'upper' or 'lower'")

        indexes, index_vars = isel_indexes(self.xindexes, slice_new)
        variables = {}

        for name, var in self.variables.items():
            if name in index_vars:
                variables[name] = index_vars[name]
            elif dim in var.dims:
                if name in self.data_vars:
                    variables[name] = var.isel(slice_end) - var.isel(slice_start)
                else:
                    variables[name] = var.isel(slice_new)
            else:
                variables[name] = var

        difference = self._replace_with_new_dims(variables, indexes=indexes)

        if n > 1:
            return difference.diff(dim, n - 1)
        else:
            return difference
Calculate the n-th order discrete difference along given axis.

        Parameters
        ----------
        dim : Hashable
            Dimension over which to calculate the finite difference.
        n : int, default: 1
            The number of times values are differenced.
        label : {"upper", "lower"}, default: "upper"
            The new coordinate in dimension ``dim`` will have the
            values of either the minuend's or subtrahend's coordinate
            for values 'upper' and 'lower', respectively.

        Returns
        -------
        difference : Dataset
            The n-th order finite difference of this object.

        Notes
        -----
        `n` matches numpy's behavior and is different from pandas' first argument named
        `periods`.

        Examples
        --------
        >>> ds = xr.Dataset({"foo": ("x", [5, 5, 6, 6])})
        >>> ds.diff("x")
        <xarray.Dataset> Size: 24B
        Dimensions:  (x: 3)
        Dimensions without coordinates: x
        Data variables:
            foo      (x) int64 24B 0 1 0
        >>> ds.diff("x", 2)
        <xarray.Dataset> Size: 16B
        Dimensions:  (x: 2)
        Dimensions without coordinates: x
        Data variables:
            foo      (x) int64 16B 1 -1

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