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'
