<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def add_columns(self, data, column_names=None, inplace=False):
 """ Returns an SFrame with multiple columns added. The number of elements in all columns must match the length of every other column of the SFrame. 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 data : list[SArray] or SFrame The columns to add. column_names: list of string, optional A list of column names. All names must be specified. ``column_names`` is ignored if data is an SFrame. inplace : bool, optional. Defaults to False. Whether the SFrame is modified in place. Returns ------- out : SFrame The current SFrame. See Also -------- add_column Examples -------- +----+-----+-----+---------+ | id | val | age | species | +----+-----+-----+---------+ | 1 | A | 3 | cat | | 2 | B | 5 | dog | | 3 | C | 9 | fossa | +----+-----+-----+---------+ [3 rows x 4 columns] """

        datalist = data
        if isinstance(data, SFrame):
            other = data
            datalist = [other.select_column(name) for name in other.column_names()]
            column_names = other.column_names()

            my_columns = set(self.column_names())
            for name in column_names:
                if name in my_columns:
                    raise ValueError("Column '" + name + "' already exists in current SFrame")
        else:
            if not _is_non_string_iterable(datalist):
                raise TypeError("datalist must be an iterable")
            if not _is_non_string_iterable(column_names):
                raise TypeError("column_names must be an iterable")

            if not all([isinstance(x, SArray) for x in datalist]):
                raise TypeError("Must give column as SArray")
            if not all([isinstance(x, str) for x in column_names]):
                raise TypeError("Invalid column name in list : must all be str")

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

        with cython_context():
            ret.__proxy__.add_columns([x.__proxy__ for x in datalist], column_names)

        ret._cache = None
        return ret