@curry
def memoize(func, cache=None, key=None):
    if cache is None:
        cache = {}

    try:
        may_have_kwargs = has_kwargs(func)
        # Is unary function (single arg, no variadic argument or keywords)?
        is_unary = isunary(func)
    except TypeError:  # pragma: no cover
        may_have_kwargs = True
        is_unary = False

    if key is None:
        if is_unary:
            def key(args, kwargs):
                return args[0]
        elif may_have_kwargs:
            def key(args, kwargs):
                return (
                    args or None,
                    frozenset(kwargs.items()) if kwargs else None,
                )
        else:
            def key(args, kwargs):
                return args

    def memof(*args, **kwargs):
        k = key(args, kwargs)
        try:
            return cache[k]
        except TypeError:
            raise TypeError("Arguments to memoized function must be hashable")
        except KeyError:
            cache[k] = result = func(*args, **kwargs)
            return result

    try:
        memof.__name__ = func.__name__
    except AttributeError:
        pass
    memof.__doc__ = func.__doc__
    memof.__wrapped__ = func
    return memof
Test conversion of a list of objects to a list of dictonaries
dataset/ETHPy150Open pytoolz/toolz/toolz/functoolz.py/memoize--crossover with--dataset/ETHPy150Open openstack-infra/shade/shade/tests/unit/test_meta.py/TestMeta.test_obj_list_to_dict