Callback discussion from lesson 9

@jcatanza, to 2, the @ symbol is a decorator for a dataclass.

(Disregard the next bit, it’s a bit off topic but it was some python stuff I didn’t quite know, and I misread the question at first, so if you know what a decorator is skip to the bottom bit. I did not know this beforehand!)

See here but essentially my take on it is a decorator is used for anything that modifies a function or class.

For example, let’s look at TabularList’s source code:

class TabularList(ItemList):
    "Basic `ItemList` for tabular data."
    _item_cls=TabularLine
    _processor=TabularProcessor
    _bunch=TabularDataBunch
    def __init__(self, items:Iterator, cat_names:OptStrList=None, cont_names:OptStrList=None,
                 procs=None, **kwargs)->'TabularList':
        super().__init__(range_of(items), **kwargs)
        #dataframe is in inner_df, items is just a range of index
        if cat_names is None:  cat_names = []
        if cont_names is None: cont_names = []
        self.cat_names,self.cont_names,self.procs = cat_names,cont_names,procs
        self.copy_new += ['cat_names', 'cont_names', 'procs']
        self.preprocessed = False

    @classmethod
    def from_df(cls, df:DataFrame, cat_names:OptStrList=None, cont_names:OptStrList=None, procs=None, **kwargs)->'ItemList':
        "Get the list of inputs in the `col` of `path/csv_name`."
        return cls(items=range(len(df)), cat_names=cat_names, cont_names=cont_names, procs=procs, inner_df=df.copy(), **kwargs)

    def get(self, o):
        if not self.preprocessed: return self.inner_df.iloc[o] if hasattr(self, 'inner_df') else self.items[o]
        codes = [] if self.codes is None else self.codes[o]
        conts = [] if self.conts is None else self.conts[o]
        return self._item_cls(codes, conts, self.classes, self.col_names)

When we create a TabularList, we call from_df, and since it is a class method, we have a special cls call which means it will call the constructor with the items passed in for us. This can then be applied to any instance we want, eg take ImageDataBunch. we have things like create_from_ll, from_folder, from_df, etc.

Whereas we have @staticmethod of single_from_classes, which is used only after a function is declared.

Another useful link on Class vs Static geeksforgeeks

Difference (verbatum)
Class method vs Static Method

  • A class method takes cls as first parameter while a static method needs no specific parameters.
  • A class method can access or modify class state while a static method can’t access or modify it.
  • In general, static methods know nothing about class state. They are utility type methods that take some parameters and work upon those parameters. On the other hand class methods must have class as parameter.
  • We use @classmethod decorator in python to create a class method and we use @staticmethod decorator to create a static method in python.

When to use what?

  • We generally use class method to create factory methods. Factory methods return class object ( similar to a constructor ) for different use cases.
  • We generally use static methods to create utility functions.

This was mostly to help me understand those decorators, as I didn’t know what they were!

ACTUAL ANSWER
Now to @dataclass, the python documentation has it here

Data classes are geared more towards storing a particular state than logic-based, with less boilerplate pain. Another explaination is here

Hope that helps, and if you see anything wrong with that explanation upon further inspection/explanation let me know, I’m learning python as I go through fastai :slight_smile:

4 Likes