12

This is a skeleton of the function I want to enhance with a cache, because doing RPC (remote procedure call) involves a TCP connection to other host.

def rpc(rpc_server, rpc_func, arg):
    return rpc_server.do_rpc(rpc_func, arg)

However, the most convenient way of simply decorating it with:

@functools.lru_cache()

does not work well, beacuse rpc_server objects come and go and this parameter should be ignored by the cache.

I can write a simple memoizing code myself. No problem with that. Actually, I see no other solution.

I am unable to rewrite this function in such way that @lru_cache() decorator can be applied and rpc_server will be passed as an argument (i.e. I don't want to make rpc_server a global variable). Is it possible?

VPfB
  • 14,927
  • 6
  • 41
  • 75
  • 1
    No, I don't think that kind of partial memoization can be done any more simply than just writing it yourself. – jonrsharpe Aug 14 '16 at 09:55
  • 2
    Possible duplicate of [Make @lru\_cache ignore some of the function arguments](https://stackoverflow.com/questions/30730983/make-lru-cache-ignore-some-of-the-function-arguments) – VPfB Nov 04 '18 at 17:46

1 Answers1

15

I'm posting this just for completness. Comments are welcome, but please do not vote.


I have found a way how to satisfy the conditions from my question. I'm not going to use this code. But it shows how flexible Python is.

import functools

class BlackBox:
    """All BlackBoxes are the same."""
    def __init__(self, contents):
        # TODO: use a weak reference for contents
        self._contents = contents

    @property
    def contents(self):
        return self._contents

    def __eq__(self, other):
        return isinstance(other, type(self))

    def __hash__(self):
        return hash(type(self))

@functools.lru_cache()
def _cached_func(blackbox, real_arg):
    print("called with args:", blackbox.contents, real_arg)
    return real_arg + 1000

def cached_func(ignored_arg, real_arg):
    # ignored means ignored by the cache
    return _cached_func(BlackBox(ignored_arg), real_arg)

cached_func("foo", 1) # cache miss
cached_func("bar", 1) # cache hit

cached_func("bar", 2) # cache miss
cached_func("foo", 2) # cache hit
VPfB
  • 14,927
  • 6
  • 41
  • 75
  • Why would you ask people not to vote, and why did you not use the solution yourself? I love this solution! Did you feel like there was some problem with it. It seems like the perfect solution to me. – John Bowers Sep 24 '21 at 17:41
  • 1
    @JohnBowers I found the code somewhere on the net and later also here on SO. Any credit (votes) should belong to the author, not to me. If I'm remembering it correctly, the original task was modified and I did not need a solution. It had nothing to do with the code. I'm sorry if it looks like there was a problem. I'm not a native English speaker and often I do not succeed to express myself clearly. – VPfB Sep 24 '21 at 19:07