return attr obj if not bysource else invertdict(attr objif __name__ ='__main__'print('classic classes in xnew-style in 'class aattr class ( )attr class ( )attr class (bc)pass (print('py=>%si attr python' search =ourstrace(inheritance( )'inh\ '[inheritance ordertrace(mapattrs( )'attrs\ 'attrs =source trace(mapattrs(ibysource=true)'objs\ 'source =[attrsprint('new-style classes in and 'class (object)attr class ( )attr class ( )attr class (bc)pass (print('py=>%si attr trace(inheritance( )'inh\ 'trace(mapattrs( )'attrs\ 'trace(mapattrs(ibysource=true)'objs\ '"(object)optional in this file assumes dir gives all an instance' attributes it maps each attribute in dir result to its source by scanning either the mro order for new-style classesor the dflr order for classic classessearching each object' namespace __dict__ along the way for classic classesthe dflr order is computed with simple recursive scan the net effect is to simulate python' inheritance search in both class models this file' self-test code applies its tools to the diamond multiple-inheritance trees we saw earlier it uses python' pprint library module to display lists and dictionaries nicely --pprint pprint is its basic calland its pformat returns print string run this on python to see both classic dflr and new-style mro search orderson python the object derivation is unnecessaryand both tests give the samenew-style results importantlyattr whose value is labeled with "py=>and whose name appears in the results listsis inherited from class in classic searchbut from class in new-style searchc:\codepy - mapattrs py classic classes in xnew-style in py=> inh [attrs advanced class topics