简体   繁体   中英

How to make an index-agnostic 2-tuple?

I am implementing a function with 2 arguments and caching the result for performance ("Memoization" technique). But I see duplications in the caching function. For example:

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

The problem is that I know in advance that fn(a,b) == fn(b,a) , so I would like it to understand that the argument tuple (a,b) is equivalent to (b,a) in this case, but this function presently caches them as 2 separate entries.

Do I need to make a new class for that purpose or is there any other more elegant way? Although I know that I can cache the same function return value for both the tuples, but I would really want to know how to implement "index-agnostic" tuples.

This memoization code is just an example, I want my tuple object to be extremely general purpose which can be used in other situations also.

You can split it into two functions. The public function takes arguments in any order, and calls an internal function with the arguments sorted. The inner function is the one with the cache.

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

@memoize
def cached_fn(*args)
    # do something

This is a time-space tradeoff -- there some extra function calls in order to cut the size of the cache in half. Hopefully you don't have functions with really long argument lists, so the sorting should not add too much overhead.

This solution requires that the datatype of the arguments have a comparison function so they can be sorted. I can't think of a way to write this in a general way without such a prerequisite. When dealing with certain types you may be able to devise a custom method to canonicalize the order. Or you may be able to use your own hashing function in the cache, and make it order-agnostic.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM