The other day I learned about 100 Days Of Code, which was popular on Twitter for a while. The purpose of this article is to keep a record and output how much I, as a beginner, can grow through 100 days of study. I think there are many mistakes and difficult to read. I would appreciate it if you could point out!
--Chapter 8 structure --Page 216 of this chapter
--Progress: Pages 73-78 --Chapter 3: Classes and Inheritance ――I will write down what I often forget or didn't know about what I learned today.
Multiple inheritance shouldn't be used much, and mix-ins should be used instead.
A small class that just defines a set of additional methods that the class should provide.
Also, unlike regular classes, it doesn't have instance attributes and you don't even have to call the __init__
constructor.
Define the mix-in example as a new method added in any inherited class as follows.
class ToDictMixin(object):
def to_dict(self):
'''
Returns the attributes of this object as a dictionary
'''
return self._traverse_dict(self.__dict__)
def _traverse_dict(self, instance_dict):
'''
Receives a dictionary and returns a new dictionary output.
Parameters
----------
instance_dict: dict
Returns
-------
output : dict
To the key, instance_To the key and value of dict_traverse()
'''
output = {}
for key, value in instance_dict.items():
output[key] = self._traverse(key, value)
return output
def _traverse(self, key, value):
'''
Call the function according to the value type of the dictionary.
'''
if isinstance(value, ToDictMixin):
return value.to_dict()
elif isinstance(value, dict):
return self._traverse_dict(value)
elif isinstance(value, list):
return [self._traverse(key, i) for i in value]
elif hasattr(value, '__dict__'):
return self._traverse_dict(value.__dict__)
else: return value
Next, use this mix-in to define a class that creates a binary tree dictionary representation and output the object attributes.
class BinaryTree(ToDictMixin):
def __init__(self, value, left=None, right=None):
self.value = value
self.left = left
self.right = right
tree = BinaryTree(5,
left=BinaryTree('aaa', right=BinaryTree(4)),
right=BinaryTree(2.4, left=BinaryTree(8)))
#Display tree object attributes as a dictionary
print(tree.to_dict())
The advantage of mix-ins is that they are type independent and can override functionality when needed. For example, override the BinaryTree subclass above to hold a reference to the parent.
class BinaryTreeWithParent(BinaryTree):
def __init__(self, value, left=None,
right=None, parent=None):
super().__init__(value, left=left, right=right)
self.parent = parent
#The default implementation loops forever, so change it to handle only the values you need
def _traverse(self, key, value):
'''
If the value type is BinaryTreeWithParent attribute and the key is parent class, value.Returns value,
Otherwise, of the parent class_Changed to do the same processing as traverse
'''
if (isinstance(value, BinaryTreeWithParent) and
key == 'parent'):
return value.value #Prevent the cycle
else:
return super()._traverse(key, value)
Print with pprint for readability
import pprint
root = BinaryTreeWithParent(5)
root.left = BinaryTreeWithParent(3, parent=root)
root.left.right = BinaryTreeWithParent(13, parent=root.left)
pprint.pprint(root.to_dict())
Output result
{'left': {'left': None,
'parent': 5,
'right': {'left': None, 'parent': 3, 'right': None, 'value': 13},
'value': 3},
'parent': None,
'right': None,
'value': 5}
By defining BinaryTreeWithParent._traverse, ToDictMixin will work automatically for all classes with attributes of type BinaryTreeWithParent.
class NamedSubTree(ToDictMixin):
def __init__(self, name, tree_with_parent):
self.name = name
self.tree_with_parent = tree_with_parent
mytree = NamedSubTree('bbb',root.left.right)
pprint.pprint(mytree.to_dict())
Output result
{'name': 'bbb',
'tree_with_parent': {'left': None, 'parent': 3, 'right': None, 'value': 13}}
--Basically, use mix-in rather than multiple inheritance --Customize each class when you need a mix-in class
Recommended Posts