<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def save(self, args=None):
 """ Save prefix to NIPAP. If the object represents a new prefix unknown to NIPAP (attribute `id` is `None`) this function maps to the function :py:func:`nipap.backend.Nipap.add_prefix` in the backend, used to create a new prefix. Otherwise it maps to the function :py:func:`nipap.backend.Nipap.edit_prefix` in the backend, used to modify the VRF. Please see the documentation for the backend functions for information regarding input arguments and return values. """


        if args is None:
            args = {}

        xmlrpc = XMLRPCConnection()
        data = {
            'description': self.description,
            'comment': self.comment,
            'tags': [],
            'node': self.node,
            'type': self.type,
            'country': self.country,
            'order_id': self.order_id,
            'customer_id': self.customer_id,
            'external_key': self.external_key,
            'alarm_priority': self.alarm_priority,
            'monitor': self.monitor,
            'vlan': self.vlan,
            'avps': self.avps,
            'expires': self.expires
        }

        if self.status is not None:
            data['status'] = self.status

        for tag_name in self.tags:
            data['tags'].append(tag_name)

        if self.vrf is not None:
            if not isinstance(self.vrf, VRF):
                raise NipapValueError("'vrf' attribute not instance of VRF class.")
            data['vrf_id'] = self.vrf.id

        # Prefix can be none if we are creating a new prefix
        # from a pool or other prefix!
        if self.prefix is not None:
            data['prefix'] = self.prefix

        if self.pool is None:
            data['pool_id'] = None

        else:
            if not isinstance(self.pool, Pool):
                raise NipapValueError("'pool' attribute not instance of Pool class.")
            data['pool_id'] = self.pool.id

        # New object, create from scratch
        if self.id is None:

            # format args
            x_args = {}
            if 'from-pool' in args:
                x_args['from-pool'] = { 'id': args['from-pool'].id }
            if 'family' in args:
                x_args['family'] = args['family']
            if 'from-prefix' in args:
                x_args['from-prefix'] = args['from-prefix']
            if 'prefix_length' in args:
                x_args['prefix_length'] = args['prefix_length']

            try:
                prefix = xmlrpc.connection.add_prefix(
                    {
                        'attr': data,
                        'args': x_args,
                        'auth': self._auth_opts.options
                    })
            except xmlrpclib.Fault as xml_fault:
                raise _fault_to_exception(xml_fault)

        # Old object, edit
        else:

            # Add authoritative source to data
            data['authoritative_source'] = self.authoritative_source

            try:
                # save
                prefixes = xmlrpc.connection.edit_prefix(
                    {
                        'prefix': { 'id': self.id },
                        'attr': data,
                        'auth': self._auth_opts.options
                    })

            except xmlrpclib.Fault as xml_fault:
                raise _fault_to_exception(xml_fault)

            if len(prefixes) != 1:
                raise NipapError('Prefix edit returned %d entries, should be 1.' % len(prefixes))
            prefix = prefixes[0]

        # Refresh object data with attributes from add/edit operation
        Prefix.from_dict(prefix, self)

        # update cache
        _cache['Prefix'][self.id] = self
        if self.pool is not None:
            if self.pool.id in _cache['Pool']:
                del _cache['Pool'][self.pool.id]