<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def eval_set(self, evals, iteration=0, feval=None):
 # pylint: disable=invalid-name """Evaluate a set of data. Parameters evals : list of tuples (DMatrix, string) List of items to be evaluated. iteration : int Current iteration. feval : function Custom evaluation function. Returns ------- result: str Evaluation result string. """

        if feval is None:
            for d in evals:
                if not isinstance(d[0], DMatrix):
                    raise TypeError('expected DMatrix, got {}'.format(type(d[0]).__name__))
                if not isinstance(d[1], STRING_TYPES):
                    raise TypeError('expected string, got {}'.format(type(d[1]).__name__))
                self._validate_features(d[0])

            dmats = c_array(ctypes.c_void_p, [d[0].handle for d in evals])
            evnames = c_array(ctypes.c_char_p, [c_str(d[1]) for d in evals])
            msg = ctypes.c_char_p()
            _check_call(_LIB.XGBoosterEvalOneIter(self.handle, iteration,
                                                  dmats, evnames, len(evals),
                                                  ctypes.byref(msg)))
            return msg.value
        else:
            res = '[%d]' % iteration
            for dmat, evname in evals:
                name, val = feval(self.predict(dmat), dmat)
                res += '\t%s-%s:%f' % (evname, name, val)
            return res