gpt4 book ai didi

python装饰器参数使用函数中的变量进行包装

转载 作者:太空狗 更新时间:2023-10-30 02:46:47 25 4
gpt4 key购买 nike

我正在寻找一种方法来创建一个装饰器,使其具有一个函数参数,该函数参数实际上使用传递给函数的变量来包装它。

例如,假设我有

@cache_decorator("my_key_{}".format(foo))
def my_function(foo, bar):
pass

@cache_decorator("another_key_{}_{}".format(foo, bar)
def another_function(user, foo, bar):
pass

目标是编写一个缓存包装器。装饰器将需要缓存键,但该键将包含传递给函数的变量,并且对于它包装的每个函数都是不同的。

理想情况下,这可以让装饰器检查给定键的缓存值,如果未找到,则执行该函数以获取该值并将其缓存。这样,如果该值在缓存中,它就不会执行创建该值的代码(即 my_function)。如果未找到,则执行 my_function 并将结果存储在缓存中并返回。

另一种选择类似于 block :

def my_function(foo, bar):
cache_value("my_key_{}".format(foo),{block of code to generate value that is only called if necessary})

在 Objective-C 或 js 中,这将是一个 block ,因此我可以保持本地定义和可变的值生成,但仅在必要时执行。我对 python 太陌生了,无法完全掌握如何使用它的闭包版本来做到这一点。

谢谢!

更新
虽然下面的解决方案适用于装饰器,但我最终选择了类似 block 的路线,因为需要额外的元数据附加到每个缓存条目以确保它可以正确失效。将此元数据定义为值生成(而不是在缓存函数内部)更易于维护。这看起来像:

def my_function(foo, bar):
def value_func():
return code_to_generate_value_using_foo_bar

return get_set_cache(key, value_func, ...)

def get_set_cache(key, value_function, ...):
value = cache.get(key)
if value is None:
value = value_function()
cache.set(key, value)
return value

最佳答案

你可以让你的包装器获得一个关键的构建函数:

@cache_w_keyfunc(lambda foo, bar: (bar,))
def my_function(foo, bar):
pass

@cache_w_keyfunc(lambda user, foo, bar: (foo, bar))
def another_function(user, foo, bar):
pass

key 生成器应该返回可哈希的东西,例如字符串元组。如果它们不可哈希,例如列表,也许可以将它们转换为字符串。

此 key 构建函数获取与函数本身相同的参数并返回要使用的 key 。

def cache_w_keyfunc(keyfunc):
def real_decorator(func):
func.cache = {}
@functools.wraps(func)
def wrapper(*args, **kwargs):
# Create the key now out of the wrapped function's name and the given keys:
key = (func.__name__, keyfunc(*args, **kwargs))
try:
return func.cache[cache_key]
except KeyError:
value = func(*args, **kwargs)
func.cache.set(cache_key, value)
return value
return wrapper
return real_decorator

关于python装饰器参数使用函数中的变量进行包装,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18790270/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com