Fastai v2 code walk-thru 5

Hi Aman, I did a bit of debugging on Transform and posted something as a follow up of my earlier query in the code walkthru forum. You can find it here .

The answer in my understanding lies in _TfmMeta wherein the call function sets cls.encodes and cls.decodes if you don’t pass along an enc or dec.

%%debug
bg = Transform()

If you follow the debugger along you will see that at the call of _TfmMeta the cls (which is the Transform class) has no attribute called encodes or decodes. Then the call sets cls.encodes and cls.decodes to be TypeDispatch(). Hopefully this clarifies.

NOTE: Enter 'c' at the ipdb>  prompt to continue execution.
None
> <string>(2)<module>()

ipdb>  s
--Call--
> /Users/i077725/Documents/GitHub/fastai_dev/dev/local/data/transform.py(122)__call__()
    120         return res
    121 
--> 122     def __call__(cls, *args, **kwargs):
    123         f = args[0] if args else None
    124         n = getattr(f,'__name__',None)

ipdb>  self
*** NameError: name 'self' is not defined
ipdb>  cls
<class 'local.data.transform.Transform'>
ipdb>  cls.encodes
*** AttributeError: type object 'Transform' has no attribute 'encodes'
ipdb>  cls.decodes
*** AttributeError: type object 'Transform' has no attribute 'decodes'
ipdb>  args
cls = <class 'local.data.transform.Transform'>
args = ()
kwargs = {}
ipdb>  n
> /Users/i077725/Documents/GitHub/fastai_dev/dev/local/data/transform.py(123)__call__()
    121 
    122     def __call__(cls, *args, **kwargs):
--> 123         f = args[0] if args else None
    124         n = getattr(f,'__name__',None)
    125         if not hasattr(cls,'encodes'): cls.encodes=TypeDispatch()

ipdb>  n
> /Users/i077725/Documents/GitHub/fastai_dev/dev/local/data/transform.py(124)__call__()
    122     def __call__(cls, *args, **kwargs):
    123         f = args[0] if args else None
--> 124         n = getattr(f,'__name__',None)
    125         if not hasattr(cls,'encodes'): cls.encodes=TypeDispatch()
    126         if not hasattr(cls,'decodes'): cls.decodes=TypeDispatch()

ipdb>  f
ipdb>  getattr(f,'__name__',None)
ipdb>  n
> /Users/i077725/Documents/GitHub/fastai_dev/dev/local/data/transform.py(125)__call__()
    123         f = args[0] if args else None
    124         n = getattr(f,'__name__',None)
--> 125         if not hasattr(cls,'encodes'): cls.encodes=TypeDispatch()
    126         if not hasattr(cls,'decodes'): cls.decodes=TypeDispatch()
    127         if isinstance(f,Callable) and n in ('decodes','encodes','_'):

ipdb>  hasattr(cls,'encodes')
False
ipdb>  n
> /Users/i077725/Documents/GitHub/fastai_dev/dev/local/data/transform.py(126)__call__()
    124         n = getattr(f,'__name__',None)
    125         if not hasattr(cls,'encodes'): cls.encodes=TypeDispatch()
--> 126         if not hasattr(cls,'decodes'): cls.decodes=TypeDispatch()
    127         if isinstance(f,Callable) and n in ('decodes','encodes','_'):
    128             getattr(cls,'encodes' if n=='_' else n).add(f)

ipdb>  self.encodes
*** NameError: name 'self' is not defined
ipdb>  cls.encodes
{}
ipdb>  hasattr(cls,'decodes')
False
ipdb>  n
> /Users/i077725/Documents/GitHub/fastai_dev/dev/local/data/transform.py(127)__call__()
    125         if not hasattr(cls,'encodes'): cls.encodes=TypeDispatch()
    126         if not hasattr(cls,'decodes'): cls.decodes=TypeDispatch()
--> 127         if isinstance(f,Callable) and n in ('decodes','encodes','_'):
    128             getattr(cls,'encodes' if n=='_' else n).add(f)
    129             return f

ipdb>  cls.decodes
{}
ipdb>  n
> /Users/i077725/Documents/GitHub/fastai_dev/dev/local/data/transform.py(130)__call__()
    128             getattr(cls,'encodes' if n=='_' else n).add(f)
    129             return f
--> 130         return super().__call__(*args, **kwargs)
    131 
    132     @classmethod

ipdb>  super
<class 'super'>
ipdb>  s
--Call--
> /Users/i077725/Documents/GitHub/fastai_dev/dev/local/data/transform.py(139)__init__()
    137     "Delegates (`__call__`,`decode`) to (`encodes`,`decodes`) if `filt` matches"
    138     filt,init_enc,as_item_force,as_item,order = None,False,None,True,0
--> 139     def __init__(self, enc=None, dec=None, filt=None, as_item=False):
    140         self.filt,self.as_item = ifnone(filt, self.filt),as_item
    141         self.init_enc = enc or dec

ipdb>  self
Transform: True {} {}
ipdb>  enc
ipdb>  dec
ipdb>  as_item
False
ipdb>  self.as_item
True
ipdb>  n
> /Users/i077725/Documents/GitHub/fastai_dev/dev/local/data/transform.py(140)__init__()
    138     filt,init_enc,as_item_force,as_item,order = None,False,None,True,0
    139     def __init__(self, enc=None, dec=None, filt=None, as_item=False):
--> 140         self.filt,self.as_item = ifnone(filt, self.filt),as_item
    141         self.init_enc = enc or dec
    142         if not self.init_enc: return

ipdb>  n
> /Users/i077725/Documents/GitHub/fastai_dev/dev/local/data/transform.py(141)__init__()
    139     def __init__(self, enc=None, dec=None, filt=None, as_item=False):
    140         self.filt,self.as_item = ifnone(filt, self.filt),as_item
--> 141         self.init_enc = enc or dec
    142         if not self.init_enc: return
    143 

ipdb>  n
> /Users/i077725/Documents/GitHub/fastai_dev/dev/local/data/transform.py(142)__init__()
    140         self.filt,self.as_item = ifnone(filt, self.filt),as_item
    141         self.init_enc = enc or dec
--> 142         if not self.init_enc: return
    143 
    144         # Passing enc/dec, so need to remove (base) class level enc/dec

ipdb>  self.init_enc
ipdb>  not self.init_enc
True
ipdb>  bool(self.init_enc)
False
ipdb>  n
--Return--
None
> /Users/i077725/Documents/GitHub/fastai_dev/dev/local/data/transform.py(142)__init__()
    140         self.filt,self.as_item = ifnone(filt, self.filt),as_item
    141         self.init_enc = enc or dec
--> 142         if not self.init_enc: return
    143 
    144         # Passing enc/dec, so need to remove (base) class level enc/dec

ipdb>  n
--Return--
Transform: False {} {}
> /Users/i077725/Documents/GitHub/fastai_dev/dev/local/data/transform.py(130)__call__()
    128             getattr(cls,'encodes' if n=='_' else n).add(f)
    129             return f
--> 130         return super().__call__(*args, **kwargs)
    131 
    132     @classmethod

ipdb>  n
--Return--
None
> <string>(2)<module>()

ipdb>  n
1 Like