On Tue, May 12, 2020 at 6:31 AM Will Bradshaw <defenastra...@gmail.com> wrote:
>
> On Monday, May 11, 2020 at 4:10:56 PM UTC-4, Chris Angelico wrote:
> > On Tue, May 12, 2020 at 6:01 AM Will Bradshaw <defenastra...@gmail.com> 
> > wrote:
> > > The only options as of now are:
> > >     1. use 3 layers of wrappers to pack the slices into a custom type 
> > > that supports hashing pass this mangled version of the arguments through 
> > > lru_cache wrapper into a function that reverses the process of the first 
> > > wrapper and passes through to the underlying implementation. (see below 
> > > "code for workaround" as example)
> > >        - This is kinda jank and arguably slow. Though in my case the cost 
> > > of the calculation operation dwarfs this cost by an several orders of 
> > > magnitude.
> > >        - mapping may be unreliable and is a rather long and impenetrable 
> > > mess.
> > >     2. implementing my own custom caching for this situation which does 
> > > not scale well and is a heck of a lot of work.
> > >     3. implement a special case for slices in the lru_cache function. 
> > > However, this is just moving the problem into the functools library.
> > >
> >
> > 4. Implement __getitem__ as a wrapper around a caching lookup function
> > that simply takes the three arguments.
> >
> > def __getitem__(self, slice):
> >     return generate_values(slice.start, slice.stop, slice.step)
> >
> > @lru_cache
> > def generate_values(start, stop, step):
> >     ...
> >
> > Not sure if this makes it easy enough to not worry about the hashability.
> >
> > ChrisA
>
> does not work in the case of multi dimensional __getitem__ calls in the numpy 
> style which happens to be my case as the number of dimensions in the indexes 
> changes by case and all of the following are supported for each axis: slice, 
> array of indexes, int index, and other custom index object types which I am 
> hesitant to disclose)
>

Ah, fair enough. Was just looking for a solution that would work on
existing Python versions rather than demanding an upgrade to 3.10 :)

Your use-case isn't common, but on the other hand, making slice
objects hashable doesn't seem like it'd break anything. Obviously
they'd only be hashable if start/stop/step are all hashable, but
that's no different from tuples. +0.5.

BTW, your third option (moving the problem to functools) might
actually be easier than you think. You'd ultimately just be changing
the behaviour of _make_key. Unfortunately there's no easy way to
replace that function for a specific lru_cache, but that might itself
be a useful feature. Imagine this:

@lru_cache(make_key=hashable_slices)
def __getitem__(self, item):
    ...

Current implementation has a single global _make_key function that
then gets snapshotted into the closure, so you could do something
hacky as a proof of concept:

old = functools._make_key
functools._make_key = hashable_slices
@lru_cache
def __getitem__(self, item):
    ...
functools._make_key = old

Obviously that's bad code, but it's a great low-effort proof of concept :)

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list

Reply via email to