python - 识别等效的可变参数函数调用以进行内存

标签 python decorator memoization

我正在使用 this decorator 的变体用于内存:

# note that this decorator ignores **kwargs
def memoize(obj):
    cache = obj.cache = {}

    @functools.wraps(obj)
    def memoizer(*args, **kwargs):
        if args not in cache:
            cache[args] = obj(*args, **kwargs)
        return cache[args]
    return memoizer

我想知道,是否有一种合理的方法可以基于 args 和 kwargs 进行内存,特别是在两个函数调用指定的参数分配不同的位置和情况的情况下通过关键字,但有完全相同的参数?

最佳答案

如果您使用参数始终作为位置或始终作为关键字,Thorsten 解决方案可以正常工作。但是,如果您想考虑为参数提供相同值的相同调用,而与参数的传递方式无关,那么您必须做一些更复杂的事情:

import inspect


def make_key_maker(func):
    args_spec = inspect.getargspec(func)

    def key_maker(*args, **kwargs):
        left_args = args_spec.args[len(args):]
        num_defaults = len(args_spec.defaults or ())
        defaults_names = args_spec.args[-num_defaults:]

        if not set(left_args).symmetric_difference(kwargs).issubset(defaults_names):
            # We got an error in the function call. Let's simply trigger it
            func(*args, **kwargs)

        start = 0
        key = []
        for arg, arg_name in zip(args, args_spec.args):
            key.append(arg)
            if arg_name in defaults_names:
                start += 1

        for left_arg in left_args:
            try:
                key.append(kwargs[left_arg])
            except KeyError:
                key.append(args_spec.defaults[start])

            # Increase index if we used a default, or if the argument was provided
            if left_arg in defaults_names:
                start += 1
        return tuple(key)

    return key_maker

上述函数尝试将关键字参数(和默认值)映射到位置,并使用结果元组作为键。我对其进行了一些测试,似乎在大多数情况下都可以正常工作。 当目标函数也使用 **kwargs 参数时,它会失败。

>>> def my_function(a,b,c,d,e=True,f="something"): pass
... 
>>> key_maker = make_key_maker(my_function)
>>> 
>>> key_maker(1,2,3,4)
(1, 2, 3, 4, True, 'something')
>>> key_maker(1,2,3,4, e=True)               # same as before
(1, 2, 3, 4, True, 'something')
>>> key_maker(1,2,3,4, True)                 # same as before
(1, 2, 3, 4, True, 'something')
>>> key_maker(1,2,3,4, True, f="something")  # same as before
(1, 2, 3, 4, True, 'something')
>>> key_maker(1,2,3,4, True, "something")    # same as before
(1, 2, 3, 4, True, 'something')
>>> key_maker(1,2,3,d=4)                     # same as before
(1, 2, 3, 4, True, 'something')
>>> key_maker(1,2,3,d=4, f="something")      # same as before
(1, 2, 3, 4, True, 'something')

关于python - 识别等效的可变参数函数调用以进行内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14621838/

相关文章:

python - 在 python 中创建漂亮的列输出

python - 如何轻松处理 python 中的动态装饰器?

python - 如何使用基于类的装饰器的缩写符号向 __call__ 提供 *args 和 **kwargs?

python pandas 传输dataframe的格式

python - 如何将函数 GROUPWISELY 应用于数据框的所有列? (在Python Pandas 中)

javascript - 为什么我的硬币找零功能在包含在内存缓存中时不起作用?

scala - Maps 中的 "get"方法是否具有 Scala 中的默认值?

scheme - 涉及二项式系数的内存

python - api查询的pandas df

python - 使用装饰器