Python缓存创建的列表

Python缓存创建的列表,python,python-3.x,Python,Python 3.x,我必须写一个函数,它有三个参数。缓存越低,越高。 “较低”和“较高”给出了创建新列表的范围。本部分为本代码: def one_range(lower, higher, cache): list1 = [] for i in range(lower,higher): list1.append(i) return list1 如果使用相同的参数调用了两次“range”,则两次都应返回相同的列表。第二次列表不会再次生成,而是重新使用。 我该怎么做 编辑

我必须写一个函数,它有三个参数。缓存越低,越高。 “较低”和“较高”给出了创建新列表的范围。本部分为本代码:

def one_range(lower, higher, cache):
    list1 = []
    for i in range(lower,higher):
        list1.append(i)
    return list1    
如果使用相同的参数调用了两次“range”,则两次都应返回相同的列表。第二次列表不会再次生成,而是重新使用。 我该怎么做


编辑了原始函数

假设您的参数是可散列的,您可以使用(Python 3.2+):

较小的点:

  • 字典用于缓存结果,因此位置参数和关键字参数都必须是可散列的
  • 尽量避免使用隐藏(屏蔽)现有内置名称的名称命名对象,例如
    range
    list
  • 使用
    mrange.cache\u clear()
    清除缓存
例如:

>>> mrange(1, 10)
mrange was called
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> mrange(1, 10)
[1, 2, 3, 4, 5, 6, 7, 8, 9]
c = {}
x = one_range(2, 4, c)
y = one_range(1, 4, c)
z = one_range(2, 4, c)
print(x is z) # True
print(c)      # {(2, 4): [2, 3], (1, 4): [1, 2, 3]}

假设
cache
是一个字典,您可以从其他参数生成一个
tuple
,并查看该tuple是否在dict中。如果在dict中,则从dict返回值,否则计算值并在返回前将其存储在dict中。您还可以为
cache
提供一个默认值,以便在不使用该值的情况下也可以使用该函数

def one_range(lower, higher, cache=None):
    if cache is not None and (lower, higher) in cache:
        return cache[(lower, higher)]
    lst = []
    for i in range(lower,higher):
        lst.append(i)
    if cache is not None:
        cache[(lower, higher)] = lst
    return lst
例如:

>>> mrange(1, 10)
mrange was called
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> mrange(1, 10)
[1, 2, 3, 4, 5, 6, 7, 8, 9]
c = {}
x = one_range(2, 4, c)
y = one_range(1, 4, c)
z = one_range(2, 4, c)
print(x is z) # True
print(c)      # {(2, 4): [2, 3], (1, 4): [1, 2, 3]}
这是很多锅炉板代码,虽然,混乱的功能。实际上,使用函数装饰器可以更轻松地完成这项工作。如果不能使用
functools.lru\u cache
,只需几行代码即可实现自己的备忘录装饰器:

def memo(f):
    f.cache = {}
    def _f(*args, **kwargs):
        if args not in f.cache:
            f.cache[args] = f(*args, **kwargs)
        return f.cache[args]
    return _f
然后在您的函数上使用它,而不再需要
缓存
参数:

@memo
def one_range(lower, higher):
    lst = []
    for i in range(lower,higher):
        lst.append(i)
    return lst

不要调用函数
范围
。您将无法从其内部调用原始的
范围
…也不要调用您的列表列表…谢谢,更正了代码:)缓存可变对象似乎有点危险-如果函数的任何调用方修改返回的列表,使用相同参数的未来调用方将获得修改后的版本!谢谢你的回答。不幸的是,这是一项大学任务,我们不能使用任何额外的工具。很好。我只关心一件事:我们返回一个列表,调用者可以修改该列表,更改所有先前调用者的值,这可能会产生意外的结果(哦,刚才看到jasonharper的评论也是如此)@Jean-Françoisfar说得很好。在第一种方法中,可以执行
返回列表(缓存[(更低,更高)])
;使用一个通用的
@memo
装饰器会更复杂一些。另一个技巧是使用一个可变的默认参数作为存储。这一次,它将很好地利用这一“特点”。缺点是无法在以下情况下清除缓存:way@Jean-Françoisfare这的确是个好主意,但考虑到它的非直觉行为也可能非常令人恼火,特别是当你刚刚接触Python,甚至被老师认为是bug时。