我正在使用 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/