Set Index or MultiIndex name.

        Able to set new names partially and by level.

        Parameters
        ----------
        names : label or list of label
            Name(s) to set.
        level : int, label or list of int or label, optional
            If the index is a MultiIndex, level(s) to set (None for all
            levels). Otherwise level must be None.
        inplace : bool, default False
            Modifies the object directly, instead of creating a new Index or
            MultiIndex.

        Returns
        -------
        Index
            The same type as the caller or None if inplace is True.

        See Also
        --------
        Index.rename : Able to set new names without level.

        Examples
        --------
        >>> idx = pd.Index([1, 2, 3, 4])
        >>> idx
        Int64Index([1, 2, 3, 4], dtype='int64')
        >>> idx.set_names('quarter')
        Int64Index([1, 2, 3, 4], dtype='int64', name='quarter')

        >>> idx = pd.MultiIndex.from_product([['python', 'cobra'],
        ...                                   [2018, 2019]])
        >>> idx
        MultiIndex(levels=[['cobra', 'python'], [2018, 2019]],
                   codes=[[1, 1, 0, 0], [0, 1, 0, 1]])
        >>> idx.set_names(['kind', 'year'], inplace=True)
        >>> idx
        MultiIndex(levels=[['cobra', 'python'], [2018, 2019]],
                   codes=[[1, 1, 0, 0], [0, 1, 0, 1]],
                   names=['kind', 'year'])
        >>> idx.set_names('species', level=0)
        MultiIndex(levels=[['cobra', 'python'], [2018, 2019]],
                   codes=[[1, 1, 0, 0], [0, 1, 0, 1]],
                   names=['species', 'year'])

def set_names(self, names, level=None, inplace=False):
        """
        Set Index or MultiIndex name.

        Able to set new names partially and by level.

        Parameters
        ----------
        names : label or list of label
            Name(s) to set.
        level : int, label or list of int or label, optional
            If the index is a MultiIndex, level(s) to set (None for all
            levels). Otherwise level must be None.
        inplace : bool, default False
            Modifies the object directly, instead of creating a new Index or
            MultiIndex.

        Returns
        -------
        Index
            The same type as the caller or None if inplace is True.

        See Also
        --------
        Index.rename : Able to set new names without level.

        Examples
        --------
        >>> idx = pd.Index([1, 2, 3, 4])
        >>> idx
        Int64Index([1, 2, 3, 4], dtype='int64')
        >>> idx.set_names('quarter')
        Int64Index([1, 2, 3, 4], dtype='int64', name='quarter')

        >>> idx = pd.MultiIndex.from_product([['python', 'cobra'],
        ...                                   [2018, 2019]])
        >>> idx
        MultiIndex(levels=[['cobra', 'python'], [2018, 2019]],
                   codes=[[1, 1, 0, 0], [0, 1, 0, 1]])
        >>> idx.set_names(['kind', 'year'], inplace=True)
        >>> idx
        MultiIndex(levels=[['cobra', 'python'], [2018, 2019]],
                   codes=[[1, 1, 0, 0], [0, 1, 0, 1]],
                   names=['kind', 'year'])
        >>> idx.set_names('species', level=0)
        MultiIndex(levels=[['cobra', 'python'], [2018, 2019]],
                   codes=[[1, 1, 0, 0], [0, 1, 0, 1]],
                   names=['species', 'year'])
        """

        if level is not None and not isinstance(self, ABCMultiIndex):
            raise ValueError('Level must be None for non-MultiIndex')

        if level is not None and not is_list_like(level) and is_list_like(
                names):
            msg = "Names must be a string when a single level is provided."
            raise TypeError(msg)

        if not is_list_like(names) and level is None and self.nlevels > 1:
            raise TypeError("Must pass list-like as `names`.")

        if not is_list_like(names):
            names = [names]
        if level is not None and not is_list_like(level):
            level = [level]

        if inplace:
            idx = self
        else:
            idx = self._shallow_copy()
        idx._set_names(names, level=level)
        if not inplace:
            return idx