make the encoder function

def make_encoder(self,formula_dict,inter_list,param_dict):
        """
        make the encoder function
        """
        X_dict = {}
        Xcol_dict = {}
        encoder_dict = {}
        # first, replace param_dict[key] = values, with param_dict[key] = dmatrix
        for key in formula_dict:
            encoding,arg = formula_dict[key]
            if 'Dev' in encoding:
                # make deviation encoded design matrix
                drop_name = arg
                # encode
                deviation_encoder,X_sub,colnames_sub = _dev_encode(param_dict,drop_name,key)
                # additionally, store in dictionary for use by interactions
                X_dict[key] = X_sub
                Xcol_dict[key] = colnames_sub
                # store dictionary of encoder functions to keep for prediction
                encoder_dict[key] = deviation_encoder
            elif 'Dum' in encoding:
                # make dummy variable encoding design mat
                ref_name = arg
                dummy_encoder,X_sub,colnames_sub = _dum_encode(param_dict,ref_name,key)
                # additionally, store in dictionary for use by interactions
                X_dict[key] = X_sub
                Xcol_dict[key] = colnames_sub
                # store dictionary of encoder functions to keep for prediction
                encoder_dict[key] = dummy_encoder
            elif 'Poly' in encoding:
                # make polynomial encoding design mat
                degree = arg
                polynomial_encoder,X_sub,colnames_sub = _poly_encode(param_dict,degree,key)
                # additionally, store in dictionary for use by interactions
                X_dict[key] = X_sub
                Xcol_dict[key] = colnames_sub
                # store dictionary of encoder functions to keep for prediction
                encoder_dict[key] = polynomial_encoder
            else:
                print encoding
                raise Exception("Encoding name error")
        # now compute interaction designmatrices
        for interaction in inter_list:
            if len(interaction) >= 3:
                raise Exception("Doesn't allow 4-way or higher interaction terms")
            elif len(interaction) == 3:

                param_name1 = interaction[0]
                param_name2 = interaction[1]
                param_name3 = interaction[2]
                col_names1 = Xcol_dict[param_name1]
                col_names2 = Xcol_dict[param_name2]
                col_names3 = Xcol_dict[param_name3]

                # make 3-way encoder function
                def threeway_encoder(param_name1,param_name2,param_name3, \
                                     col_names1, col_names2, col_names3, X_dict):
                    """
                    needs the three names of the parameters to be encoded, as well as
                    a dictionary containing the already encoded single parameter 
                    design matrices, keyed by name
                    """
                    X1 = X_dict[param_name1]
                    X2 = X_dict[param_name2]
                    X3 = X_dict[param_name3]

                    X_int = []
                    names_int = []
                    for i in np.arange(0,X1.shape[1]):
                        for j in np.arange(0,X2.shape[1]):
                            for k in np.arange(0,X3.shape[1]):
                                X_int.append(X1[:,i]*X2[:,j]*X3[:,k])
                                names_int.append(col_names1[i] + "*" + \
                                                 col_names2[j] + "*" + col_names3[k])
                    # make X_int from lists to np array
                    X_int = np.array(X_int).T
                    return X_int, names_int
                encoder_dict['threeway'] = threeway_encoder

            elif len(interaction) == 2:
                # there are two interaction terms (A*B)

                param_name1 = interaction[0]
                param_name2 = interaction[1]
                col_names1  = Xcol_dict[param_name1]
                col_names2  = Xcol_dict[param_name2]

                # make twoway_encoder function
                def twoway_encoder(param_name1,param_name2, col_names1, col_names2, X_dict):
                    X1 = X_dict[param_name1]
                    X2 = X_dict[param_name2]

                    X_int = []
                    names_int = []
                    for i in np.arange(0,X1.shape[1]):
                        for j in np.arange(0,X2.shape[1]):
                            X_int.append(X1[:,i]*X2[:,j])
                            names_int.append(col_names1[i] + "*" + col_names2[j])
                    X_int = np.array(X_int).T
                    return X_int, names_int
                encoder_dict['twoway'] = twoway_encoder
            else:
                raise Exception("Error while evaluating meaning of interaction term")

        # make key in encoder to specify which columns are active
        encoder_dict['trimmed_columns'] = self._trimmed_columns
        return encoder_dict