<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def url_for(self, entity=None, object_type=None, object_id=None, **kwargs):
 """Return canonical view URL for given entity instance. If no view has been registered the registry will try to find an endpoint named with entity's class lowercased followed by '.view' and that accepts `object_id=entity.id` to generates an url. :param entity: a instance of a subclass of :class:`abilian.core.extensions.db.Model`, :class:`whoosh.searching.Hit` or :class:`python:dict` :param object_id: if `entity` is not an instance, this parameter must be set to target id. This is usefull when you know the type and id of an object but don't want to retrieve it from DB. :raise KeyError: if no view can be found for the given entity. """

        if object_type is None:
            assert isinstance(entity, (db.Model, Hit, dict))
            getter = attrgetter if isinstance(entity, db.Model) else itemgetter
            object_id = getter("id")(entity)
            object_type = getter("object_type")(entity)

        url_func = self._map.get(object_type)  # type: Optional[Callable]
        if url_func is not None:
            return url_func(entity, object_type, object_id, **kwargs)

        try:
            return url_for(
                "{}.view".format(object_type.rsplit(".")[-1].lower()),
                object_id=object_id,
                **kwargs
            )
        except Exception:
            raise KeyError(object_type)