如何制作索引不可知的二元组?

How to make an index-agnostic 2-tuple?

我正在实现一个带有 2 个参数的函数并缓存结果以提高性能("Memoization" 技术)。但是我在缓存功能中看到了重复。例如:

@memoize
def fn(a,b):
    #do something.

问题是我事先知道fn(a,b) == fn(b,a),所以我希望它理解参数元组(a,b)在这种情况下等同于(b,a),但是这个函数目前将它们缓存为 2 个单独的条目。

我需要为此目的制作一个新的 class 还是有其他更优雅的方法?虽然我知道我可以为两个元组缓存相同的函数 return 值,但我真的很想知道如何实现 "index-agnostic" 元组。

这个记忆代码只是一个例子,我希望我的元组对象非常通用,也可以在其他情况下使用。

如果您想要一个非常通用的解决方案,不仅针对两个参数,而且可能针对多个参数,其中 (a, b, a)(a, a, b) 的处理方式相同,但与 (a, b, b) 的处理方式不同,您可以使用 frozenset(Counter(argument_tuple).items()) 来计算每个值的出现次数,并将生成的 dict 转换为冻结的元组集(在 from collections import Counter 之后)。

您可以将其拆分为两个函数。 public 函数以任意顺序接受参数,并调用一个内部函数,并将参数排序。内部函数是带缓存的那个。

def fn(*args):
    return cached_fn(*sorted(args))

@memoize
def cached_fn(*args)
    # do something

这是一个时间-space 权衡 -- 有一些额外的函数调用是为了将缓存的大小减半。希望您没有带有很长参数列表的函数,因此排序不应增加太多开销。

此解决方案要求参数的数据类型具有比较功能,以便对它们进行排序。如果没有这样的先决条件,我想不出一种通用的方式来写这个。在处理某些类型时,您可以设计一种自定义方法来规范化订单。或者您可以在缓存中使用您自己的哈希函数,并使其与顺序无关。