<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def angle_iter(self, g_nums, ats_1, ats_2, ats_3, invalid_error=False):
 """ Iterator over selected atomic angles. Angles are in degrees as with :meth:`angle_single`. See `above <toc-generators_>`_ for more information on calling options. Parameters g_nums |int| or iterable |int| or |None| -- Index of the desired geometry ats_1 |int| or iterable |int| or |None| -- Index of the first atom ats_2 |int| or iterable |int| or |None| -- Index of the second atom ats_3 |int| or iterable |int| or |None| -- Index of the third atom invalid_error |bool|, optional -- If |False| (the default), |None| values are returned for results corresponding to invalid indices. If |True|, exceptions are raised per normal. Yields ------ angle |npfloat_| -- Spanning angles in degrees between corresponding |br| `ats_1`-`ats_2`-`ats_3`, from geometry/geometries `g_nums` Raises ------ ~exceptions.IndexError If an invalid (out-of-range) `g_num` or `at_#` is provided. ~exceptions.ValueError If all iterable objects are not the same length. ~exceptions.ValueError If any `ats_2` element is equal to either the corresponding `ats_1` or `ats_3` element. """

        # Suitability of ats_n indices will be checked within the
        #  self.angle_single() calls and thus no check is needed here.

        # Import the tuple-generating function
        from .utils import pack_tups

        # Print the function inputs if debug mode is on
        if _DEBUG:   # pragma: no cover
            print("g_nums = {0}".format(g_nums))
            print("ats_1 = {0}".format(ats_1))
            print("ats_2 = {0}".format(ats_2))
            print("ats_3 = {0}".format(ats_3))
        ## end if

        # Perform the None substitution
        arglist = self._none_subst(g_nums, ats_1, ats_2, ats_3)

        # Expand/pack the tuples from the inputs
        tups = pack_tups(*arglist)

        # Dump the results if debug mode is on
        if _DEBUG:  # pragma: no cover
            print(tups)
        ## end if

        # Construct the generator using the packed tuples.
        for tup in tups:
            if _DEBUG: # pragma: no cover
                print(tup)
            ## end if

            yield self._iter_return(tup, self.angle_single, invalid_error)