[Python-ideas] Fwd: Using functools.lru_cache only on some arguments of a function

Franklin? Lee leewangzhong+python at gmail.com
Tue Jan 12 18:26:07 EST 2016


On Sun, Jan 10, 2016 at 3:27 AM, Bill Winslow <bunslow at gmail.com> wrote:
> Sorry for the late reply everyone.
>
> I think relying on closures, while a solution, is messy. I'd still much
> prefer a way to tell lru_cache to merely ignore certain arguments.

Wait, why is it messy? The function is created inside the outer
function, and never gets released to the outside. I think it's
cleaner, because it's encapsulating the recursive part, the memo, and
the cached work. Besides, `lru_cache` is implemented using a closure,
and your solution of passing a key function might be used with a
closure on a nested function.

If you're solving dynamic programming puzzles, an outer/inner pairing
of non-recursive/recursive represents the fact that your memoization
can't be reused for different instances of the same problem. (See, for
example, Edit Distance
(https://web.stanford.edu/class/cs124/lec/med.pdf), in which your
recursive parameters are indices into your non-recursive parameters.)


> I've further considered my original proposal, and rather than naming it
> "arg_filter", I realized that builtins like sorted(), min(), max(), etc all
> already have the exact same thing -- a "key" argument which transforms the
> elements to the user's purpose. (In the sorted/min/max case, it's called on
> the elements of the argument rather than the argument itself, but it's still
> the same concept.) So basically, my original proposal with renaming from
> arg_filter to key, is tantamount to extending the same functionality from
> sorted/min/max to lru_cache as well.

I like this conceptually, because the `key` parameter sort of lets you
customize the cache dict (or whatever). You can use, for example,
`str.lower` (though not directly).

Note that the key parameter in those other functions allows you to
call the key function only once per element, which is impossible for
this.

Should it be possible to specify a tuple for `key` to transform each
arg separately? In your case, you might pass in `(None, lambda x: 0)`
to specify that the first parameter shouldn't be transformed, and the
second parameter should be considered constant. But that's very
confusing: should `None` mean "ignore", or "don't transform" (like
`filter`)? Or we can use `False` for "ignore", perhaps.


On Sun, Jan 10, 2016 at 2:03 PM, Michael Selik <mike at selik.org> wrote:
> Shouldn't the key function be called with ``key(*args, **kwargs)``?

Does `lru_cache` know how to deal with passing regular args as kwargs? Does it


More information about the Python-ideas mailing list