Aug-05-2018, 03:23 PM
Hi,
I am learning Python classes and I have hit a roadblock in one particular file. So, I coded a file(listtree.py) which has a self-test code with a module listed below(testmixin.py). When I am running listtree.py, I am getting an error which I cannot understand(listed below). Please let me know if anyone can help me out on this. Have been staring at it for an hour but no luck.
-Arjun
I am learning Python classes and I have hit a roadblock in one particular file. So, I coded a file(listtree.py) which has a self-test code with a module listed below(testmixin.py). When I am running listtree.py, I am getting an error which I cannot understand(listed below). Please let me know if anyone can help me out on this. Have been staring at it for an hour but no luck.

-Arjun
#!python # File: listtree.py (2.X + 3.X) class ListTree: """ Mix-in that returns an __str__ trace of the entire class tree and all its objects' attrs at and above self; run by print(), str() returns constructed string; uses __X attr names to avoid impacting clients; recurses to superclasses explicitly, uses str.format()for clarity; """ def __attrnames(self, obj, indent): spaces = ' ' * (indent+ 1) result = '' for attr in sorted(obj.__dict__): if attr.startswith('__') and attr.endswith('__'): result += spaces + '{0}\n'.format(attr) else: result += spaces + '{0}={1}\n'.format(attr, getattr(obj, attr)) return result def __listclass(self, aClass, indent): dots = '.' * indent if aClass in self.__visited: return '\n{0}<Class {1}:, address {2}: (see above)>\n'.format( dots, aClass.__name__, id(aClass)) else: self.__visited[aClass] = True here = self.__attrnames(aClass, indent) above = '' for super in aClass.__bases__: above += self.__listclass(super, indent+4) return '\n{0}<Class {1}, address {2}: \n{3}{4}{5}>\n'.format( dots, aClass.__name__, id(aClass), here, above, dots) def __str__(self): self.__visited = {} here = self.__attrnames(self, 0) above = self.__listclass(self.__class__, 4) return '<Instance of {0}, address {1}:\n{2]{3}>'.format( self.__class.__name__, id(self), here, above) if __name__ == '__main__': import testmixin testmixin.tester(ListTree)
#!python # File: testmixin.py (2.X + 3.X) """ Generic lister mixin tester: similar to transitive reloader in Chapter 25, but passes a class object to tester (not function), and testbyNames adds loading of both module and class by name string here, in keeping with Chapter 31's factory pattern. """ import importlib def tester(listerclass, sept=False): class Super: def __init__(self): # Superclass __init__ self.data1 = 'spam' # Create instance attrs def ham(self): pass class Sub(Super, listerclass): # Mix in ham and a __str__ def __init__(self): # Listers have access to self Super.__init__(self) self.data2 = 'eggs' # More instance attrs self.data3 = 42 def spam(self): # Define another method here pass instance = Sub() # Return instance with lister's __str__ print(instance) # Run mixed-in __str__ (or via str(x)) if sept: print('-' * 80) def testbyNames(modname, classname, sept=False): modobject = importlib.import_module(modname) # Import by namestring listerclass = getattr(modobject, classname) # Fetch attr by name string tester(listerclass, sept) if __name__ == '__main__': testbyNames('listtree', 'ListTree', False)
Error:Traceback (most recent call last):
File "C:\Users\Ganga Mohan\AppData\Local\Programs\Python\Python36-32\listtree.py", line 58, in <module>
testmixin.tester(ListTree)
File "C:\Users\Ganga Mohan\AppData\Local\Programs\Python\Python36-32\testmixin.py", line 36, in tester
print(instance) # Run mixed-in __str__ (or via str(x))
File "C:\Users\Ganga Mohan\AppData\Local\Programs\Python\Python36-32\listtree.py", line 51, in __str__
self.__class.__name__,
AttributeError: 'Sub' object has no attribute '_ListTree__class'