def rename(self, names, inplace=False):
        """
        Returns an SFrame with columns renamed. ``names`` is expected to be a
        dict specifying the old and new names. This changes the names of the
        columns given as the keys and replaces them with the names given as the
        values.

        If inplace == False (default) this operation does not modify the
        current SFrame, returning a new SFrame.

        If inplace == True, this operation modifies the current
        SFrame, returning self.

        Parameters
        ----------
        names : dict [string, string]
            Dictionary of [old_name, new_name]

        inplace : bool, optional. Defaults to False.
            Whether the SFrame is modified in place.

        Returns
        -------
        out : SFrame
            The current SFrame.

        See Also
        --------
        column_names

        Examples
        --------
        >>> sf = SFrame({'X1': ['Alice','Bob'],
        ...              'X2': ['123 Fake Street','456 Fake Street']})
        >>> res = sf.rename({'X1': 'name', 'X2':'address'})
        >>> res
        +-------+-----------------+
        |  name |     address     |
        +-------+-----------------+
        | Alice | 123 Fake Street |
        |  Bob  | 456 Fake Street |
        +-------+-----------------+
        [2 rows x 2 columns]
        """
        if (type(names) is not dict):
            raise TypeError('names must be a dictionary: oldname -> newname')
        all_columns = set(self.column_names())
        for k in names:
            if not k in all_columns:
                raise ValueError('Cannot find column %s in the SFrame' % k)

        if inplace:
            ret = self
        else:
            ret = self.copy()

        with cython_context():
            for k in names:
                colid = ret.column_names().index(k)
                ret.__proxy__.set_column_name(colid, names[k])
        ret._cache = None
        return ret