【发布时间】:2020-03-22 08:30:54
【问题描述】:
这个例子是人为的,但代表了现实生活中的情况:
我有一个接受命令行参数的 python 脚本。
main()将解析参数,并将它们传递给中间函数(代码示例中的caller_func)然后中间函数将调用一个装饰函数(示例中为
fib()),该函数使用functools中的lru_cache进行装饰,并且缓存的maxsize是要接受的参数命令行并通过中间函数传递。
我该怎么做?
import argparse
from functools import lru_cache
def main():
# boilerplate for parsing command line arguments
parser = argparse.ArgumentParser()
parser.add_argument("--cache_size", default="10")
parser.add_argument("--fibo_num", default="20")
args = parser.parse_args()
cache_size = int(args.cache_size)
fibo_num = int(args.fibo_num)
caller_func(cache_size, fibo_num)
#Intermediate function that is supposed to call decorated function
def caller_func(cache_size, fib_num):
print(fib(fib_num))
#function decorated by LRU cache
@lru_cache(maxsize=cache_size)
def fib(n):
if n < 2:
return n
return fib(n-1) + fib(n-2)
if __name__ == "__main__":
main()
运行方式
python3 example.py --cache_size 5 --fibo_num 30
抛出
NameError: name 'cache_size' is not defined
我尝试将cache_size 设为全局变量,但没有奏效,而且我也不想要全局变量。
【问题讨论】:
-
装饰器在定义时执行,甚至在调用 main 之前。
-
也许在这里使用部分函数:stackoverflow.com/a/25827070/3279716
-
很好的诊断@jonrsharpe。那有什么解决办法呢?是否可以从命令行参数装饰这个装饰器?
-
你不必像那样应用装饰器;鉴于中间体无论如何都需要缓存大小(到目前为止是什么?)你可以调用
lru_cache(maxsize=cache_size)(fib)(fibo_num)。 -
lru_cache(maxsize=cache_size)(fib)(fibo_num)不会做你想做的事,因为它不会将函数fib重新分配给修饰版本;所以递归调用将在不使用缓存的未修饰的fib函数上。
标签: python python-3.x decorator argparse python-decorators