考虑用Mix-in组件代替多继承

Python是面向对象的编程语言,它提供了一些内置的编程机制,使得开发者可以适当地实现多继承。但是,我们仍然应该尽量避开多继承。

若一定要利用多继承所带来的便利及封装性,那就考虑编写min-in类。min-in是一种小型的类,它只定义了其他类可能需要提供的一套附加方法,而不定义自己的属性,此外,它也不要求使用者调用自己的__init__构造器。

min-in的最大优势在于,使用者可以随时安插这些通用的功能,并且在必要时覆写它们,多个min-in直接也可以相互组合。有了这样的min-in之后,我们只需要编写极其少量的代码,就可以通过继承体系,轻松地创建出相关工具类。

要点:

1.能用min-in组件实现的效果,就不要用多继承来做。

2.将各功能实现为可插拔的min-in组件,然后继承之。

3.将简单的行为封装到min-in组件里,然后就可以用多个min-in组合出复杂的行为。

例如,我们需要把Python实例对象以字典形式输出,以便将其序列化,我们不妨把这个功能写成通用代码,以供其他类使用。

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

再如,我们可以编写一个min-in,它能为任意类提供通用的JSON序列化功能,我们可以假设:继承了min-in的那个类,会提供名为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())

 然后,我们定义一个测试类,同时继承上述两个min-in,以达到扩展功能的作用。

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}')

测试运行结果:

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)

运行结果:

运行结果显示,已成功为Person类通过min-in扩展的形式,为其添加了新功能 :将Python实例对象以字典形式输出、将Python实例对象以JSON字符串形式输出。

猜你喜欢

转载自blog.csdn.net/zhu6201976/article/details/109328682
今日推荐