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