Consider using Mix-in components instead of multiple inheritance

Python is an object-oriented programming language. It provides some built-in programming mechanisms so that developers can appropriately implement multiple inheritance. However, we should still try to avoid multiple inheritance.

If you must take advantage of the convenience and encapsulation that multiple inheritance brings, then consider writing min-in classes. Min-in is a small class. It only defines a set of additional methods that other classes may need to provide, without defining its own attributes. In addition, it does not require users to call their own __init__ constructor.

The biggest advantage of min-in is that users can insert these common functions at any time and overwrite them when necessary. Multiple min-in can also be combined directly. With such min-in, we only need to write a very small amount of code to easily create related tool classes through the inheritance system.

Key points:

1. If you can use min-in components, don't use multiple inheritance.

2. Implement each function as a pluggable min-in component, and then inherit it.

3. Encapsulate simple behaviors into min-in components, and then you can use multiple min-ins to combine complex behaviors.

 

For example, we need to output the Python instance object as a dictionary in order to serialize it. We might as well write this function as a general code for other classes to use.

class ToDictMixin(object):
    def to_dict(self):
        return self._traverse_dict(self.__dict__)

    def _traverse_dict(self, instance_dict):
        output = {}
        for key, value in instance_dict.items():
            output[key] = self._traverse(key, value)
        return output

    def _traverse(self, key, value):
        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

For another example, we can write a min-in, which can provide a general JSON serialization function for any class. We can assume that the class that inherits min-in will provide a method named to_dict.

class JsonMixin(object):
    @classmethod
    def from_json(cls, data):
        kwargs = json.loads(data)
        return cls(**kwargs)

    def to_json(self):
        return json.dumps(self.to_dict())

 Then, we define a test class, inherit the above two min-in at the same time, in order to achieve the role of extended functions.

class Person(ToDictMixin, JsonMixin):
    def __init__(self, name, age, address, list1, dict1):
        self.name = name
        self.age = age
        self.address = address
        self.list1 = list1
        self.dict1 = dict1

    def introduce(self):
        print(f'{self.name} {self.age} {self.address}')

Test run results:

if __name__ == '__main__':
    # 1.测试ToDictMixin
    person = Person('zhangsan', 18, 'Shenzhen', [1, 2, 3], {'username': 'admin', 'password': '123456'})
    print(person.to_dict())

    # 2.测试JsonMixin
    json_str = '{"name": "zhangsan", "age": 18, "address": "Shenzhen", "list1": [1, 2, 3], "dict1": {"username": "admin", "password": "123456"}}'
    person = Person.from_json(data=json_str)
    json_str = person.to_json()
    print(json_str)

operation result:

The results of the operation show that the Person class has been successfully extended through min-in, and new functions have been added to it: output Python instance objects in the form of a dictionary, and output Python instance objects in the form of JSON strings.

Guess you like

Origin blog.csdn.net/zhu6201976/article/details/109328682