gpt4 book ai didi

Python lru_cache 实现

转载 作者:太空宇宙 更新时间:2023-11-03 14:05:16 24 4
gpt4 key购买 nike

我试图了解 python (3) 中 lru_cache decorator 的实现,特别是它如何从函数 创建 key args 为其内部 dict

我一直在读这篇文章https://github.com/python/cpython/blob/master/Lib/functools.py#L414

我无法理解为什么函数中会有这个kwd_mark = (object(),)。我看到它正在创建一个仅包含 object() 实例的 tuple ,看起来它就像所有 args 之间的分隔符kwargs/kwds 用于函数调用的key。我想了解它是否在这里做了什么特别的https://repl.it/repls/ExpensiveFinishedSandboxes但我想不出什么。

最佳答案

链接很好,但它们很容易损坏,所以我会尝试将所有内容直接包含在答案中。我们有一个像这样的函数(简化):

def make_key(args, kwds, kwd_mark = (object(),)):
key = args
if kwds:
key += kwd_mark
for item in kwds.items():
key += item
...
return key

那里的评论相当具有描述性:

Make a cache key from <...> positional and keyword arguments. The key is constructed in a way that is flat as possible rather than as a nested structure that would take more memory.

让我们尝试一些示例运行:

>>> print(make_key((1, 2, 3), dict()))
(1, 2, 3)
>>> print(make_key((1, 2, 3), dict(a='x', b='y')))
(1, 2, 3, <object object at 0x7f6faf99d0c0>, 'a', 'x', 'b', 'y')
>>> print(make_key((1, 2, 4), dict(b='y', a='x')))
(1, 2, 4, <object object at 0x7f6faf99d0c0>, 'b', 'y', 'a', 'x')

结果是一个可散列元组,表示用户调用其 user_function 的参数。和。正如您所指出的,kwd_mark用作 args 和 kwargs 之间的哨兵值,以便单独缓存以下调用:

user_function(1, 2, 3, 'a', 'x')
user_function(1, 2, 3, a='x')
<小时/>

我们本可以使用None作为分隔符,但是如果有人用 None 调用函数怎么办?作为参数?而object()是Python中基类的一个对象,它本身并没有做太多事情,它的唯一性很有用。如果您的分隔符是独一无二的,则不能将参数与分隔符混淆!而且由于这个哨兵是在函数定义时创建的,因此它在程序运行过程中将保持不变(请注意,上面的结果引用相同的 <object object at 0x7f6faf99d0c0> ),因此它的哈希值将是相同的。

你可能会问,为什么不做 kwd_mark=object() ?我认为这里的原因是它仅用于将其“附加”到元组,因此否则您每次都必须创建一个新元组(请记住,元组是不可变的):

def make_key(args, kwds, kwd_mark=object()):
key = args
if kwds:
key += (kwd_mark, ) # new tuple
for item in kwds.items():
key += item

关于Python lru_cache 实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48941388/

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