Is there a way to be able to access the Learner instanced in typedispatched methods like show_batch and show_results?

For example:

@typedispatch
def show_results(x:MyCustomInput, y, samples, outs, ctxs=None, max_n=6, **kwargs):  
    
    # can I access the Learner instance this is called on???
    ...
    return ctxs

learn.show_results(max_n=2)

Is there a way to get at my Learner instance inside show_results? If not, it would be a nice and very helpful addition if possible.

show_results is tied to the learner in the end, see here:

So that would be how it’s accessed

Right, I get that.

But, can I access the Learner instance inside of that method?

If I try to access self in my typedispatched show_results, I get a NameError: name 'self' is not defined exception.

I think your type dispatch should be tagged onto Learner instead. You have the show_results on your DataLoader here (or Data Type). How that works exactly I’m not 100% on, but just a partial lead :slight_smile:

I’m not sure what that means :slight_smile:

As an aside, the reason I’d like to be able to access the Learner instance inside those methods is because how I want to show data is dependent on the Transforms used to create it. Unfortunately, I don’t see a way to do this. It seems like the @typedispatched method gets called with no way of being able to access the “caller” (e.g., the Learner instance).

I faced a similar issue a while ago @wgpubs . Typedispatch doesn’t allow us to reference it’s dispatcher class inside it. The silly hack i used was just to call the method i needed on the Dataloaders class directly instead of calling it on the learn.dataloaders. I hope this makes a bit of sense to you.
Cheers

Well, I don’t really like how it looks … but just passing it in as an arg works:

@typedispatch
def show_results(x:MyCustomType, y, samples, outs, learner, ctxs=None, max_n=6, **kwargs): 
    ...

# and then
learn.show_results(learner=learn)

I may be wrong but I think that typedispatch uses the type hints from the function/method to decide which function/method call. So, in your case, you could make a new instance method for Learner class with your data: def your_method(self:Learner, x:your_data_type, ...) (replace Learner with any class type you want to add). I think that if you don’t call the first argument self, typedispatch will treat as a function and not as instance method. So, to reference the dispatcher class inside the function, pass it as argument and add then a type hint. For example:

def my_func(x:int, y:int, **kwargs): pass # <- is going to be called when you use an unknown caller

def my_func(x:int, y:int, caller:MyClass=None, **kwargs): pass # <- is going to be called when you use MyClass caller


# You call it as:
my_func(x, y, caller=self) # we use caller to perform typedispatch

There are typedispatch examples here and here.

Finally, I don’t have a clear idea in case some classes are subclasses than others. I don’t know which take precedence or if matters the order definition.

That is how @patch works … @typedispatch on the otherhand looks for your_method when the first argument you pass to it is Learner.

I guess another option would be to @patch Learner.show_results to pass itself into the @typedispatched methods. This might be a nice change to the library itself come to think about it.