| Implements method / definition memoization.
    | Any method / definition decorated will get its return value cached and restored whenever called with the same arguments.

    :param cache: Alternate cache.
    :type cache: dict
    :return: Object.
    :rtype: object

def memoize(cache=None):
    """
    | Implements method / definition memoization.
    | Any method / definition decorated will get its return value cached and restored whenever called with the same arguments.

    :param cache: Alternate cache.
    :type cache: dict
    :return: Object.
    :rtype: object
    """

    if cache is None:
        cache = {}

    def memoize_decorator(object):
        """
        Implements method / definition memoization.

        :param object: Object to decorate.
        :type object: object
        :return: Object.
        :rtype: object
        """

        @functools.wraps(object)
        def memoize_wrapper(*args, **kwargs):
            """
            Implements method / definition memoization.

            :param \*args: Arguments.
            :type \*args: \*
            :param \*\*kwargs: Keywords arguments.
            :type \*\*kwargs: \*\*
            :return: Object.
            :rtype: object
            """

            if kwargs:
                key = args, frozenset(kwargs.iteritems())
            else:
                key = args

            if key not in cache:
                cache[key] = object(*args, **kwargs)

            return cache[key]

        return memoize_wrapper

    return memoize_decorator