<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def records(self, part=None, fallback=True):
 """Return an iterator over the records in the pack. Each record is supplied as a namedtuple with the channel names as field names. This is useful if each record make a meaningful data set on its own. part: int or None Same meaning as in :meth:`~channelpack.ChannelPack.__call__`. fallback: boolean The named tuple requires python-valid naming. If fallback is False, there will be an error if ``self.chnames`` is not valid names and not None. If True, fall back to the ``self.chnames_0`` on error. .. note:: The error produced on invalid names if fallback is False is not produced until iteration start. Here is a good post on stack overflow on the subject `231767 <http://stackoverflow.com/questions/231767/what-does-the-yield-keyword-do-in-python>`_ """


        names_0 = [self.chnames_0[k] for k in sorted(self.chnames_0.keys())]
        if self.chnames is not None:
            names = [self.chnames[k] for k in sorted(self.chnames.keys())]

        try:
            Record = namedtuple('Record', names)
        except NameError:       # no names
            Record = namedtuple('Record', names_0)
            names = names_0
        except ValueError:      # no good names
            if fallback:
                Record = namedtuple('Record', names_0)
                names = names_0
            else:
                raise

        for tup in zip(*[self(name, part) for name in names]):
            yield Record(*tup)