{"id":207,"date":"2024-01-25T15:54:13","date_gmt":"2024-01-25T15:54:13","guid":{"rendered":"https:\/\/learnpython.elegantwallp.com\/?p=207"},"modified":"2024-01-25T15:54:15","modified_gmt":"2024-01-25T15:54:15","slug":"python-mixin","status":"publish","type":"post","link":"https:\/\/learnpython.elegantwallp.com\/2024\/01\/25\/python-mixin\/","title":{"rendered":"Python mixin"},"content":{"rendered":"\n<p><strong>Summary<\/strong>: in this tutorial, you\u2019ll learn about Python mixin classes and how to use them to make the code reusable.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What is a mixin in Python<\/h2>\n\n\n\n<p>A mixin is a\u00a0class\u00a0that provides method implementations for reuse by multiple related child classes. However, the inheritance is not implying an is-a relationship.<\/p>\n\n\n\n<p>A mixin doesn\u2019t define a new type. Therefore, it is not intended for direction instantiation.<\/p>\n\n\n\n<p>A mixin bundles a set of\u00a0methods\u00a0for reuse. Each mixin should have a single specific behavior, implementing closely related methods.<\/p>\n\n\n\n<p>Typically, a child class uses\u00a0multiple inheritance\u00a0to combine the mixin classes with a parent class.<\/p>\n\n\n\n<p>Since Python doesn\u2019t define a formal way to define mixin classes, it\u2019s a good practice to name mixin classes with the suffix&nbsp;<code>Mixin<\/code>.<\/p>\n\n\n\n<p>A mixin class is like an interface in Java and C# with implementation. And it\u2019s like a\u00a0trait in PHP.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Python Mixin example<\/h2>\n\n\n\n<p>First, define a\u00a0<code>Person<\/code>\u00a0class:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>class Person: def __init__(self, name): self.name = name<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>Second, define an\u00a0<code>Employee<\/code>\u00a0class that inherits from the\u00a0<code>Person<\/code>\u00a0class:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>class Employee(Person): def __init__(self, name, skills, dependents): super().__init__(name) self.skills = skills self.dependents = dependents<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>Third, create a new instance of the\u00a0<code>Employee<\/code>\u00a0class:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>if __name__ == '__main__': e = Employee( name='John', skills=&#91;'Python Programming''Project Management'], dependents={'wife': 'Jane', 'children': &#91;'Alice', 'Bob']} )<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>Suppose you want to convert the\u00a0<code>Employee<\/code>\u00a0object to a\u00a0dictionary. To do that, you can add a new method to the\u00a0<code>Employee<\/code>\u00a0class, which converts the object to a dictionary.<\/p>\n\n\n\n<p>However, you may want to convert objects of other classes to\u00a0dictionaries. To make the code reusable, you can define a mixin class called\u00a0<code>DictMixin<\/code>\u00a0like the following:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>class DictMixin: def to_dict(self): return self._traverse_dict(self.__dict__) def _traverse_dict(self, attributes: dict) -> dict: result = {} for key, value in attributes.items(): result&#91;key] = self._traverse(key, value) return result def _traverse(self, key, value): if isinstance(value, DictMixin): return value.to_dict() elif isinstance(value, dict): return self._traverse_dict(value) elif isinstance(value, list): return &#91;self._traverse(key, v) for v in value] elif hasattr(value, '__dict__'): return self._traverse_dict(value.__dict__) else: return value<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>The&nbsp;<code>DictMixin<\/code>&nbsp;class has the&nbsp;<code>to_dict()<\/code>&nbsp;method that converts an object to a dictionary.<\/p>\n\n\n\n<p>The&nbsp;<code>_traverse_dict()<\/code>&nbsp;method iterates the object\u2019s attributes and assigns the key and value to the result.<\/p>\n\n\n\n<p>The attribute of an object may be a list, a dictionary, or an object with the&nbsp;<code>__dict__<\/code>&nbsp;attribute. Therefore, the&nbsp;<code>_traverse_dict()<\/code>&nbsp;method uses the&nbsp;<code>_traverse()<\/code>&nbsp;method to convert the attribute to value.<\/p>\n\n\n\n<p>To convert instances of the\u00a0<code>Employee<\/code>\u00a0class to dictionaries, the\u00a0<code>Employee<\/code>\u00a0needs to inherit from both\u00a0<code>DictMixin<\/code>\u00a0and\u00a0<code>Person<\/code>\u00a0classes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>class Employee(DictMixin, Person): def __init__(self, name, skills, dependents): super().__init__(name) self.skills = skills self.dependents = dependents<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>Note that you need to specify the mixin classes before other classes.<\/p>\n\n\n\n<p>The following creates a new instance of the\u00a0<code>Employee<\/code>\u00a0class and converts it to a dictionary:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>e = Employee( name='John', skills=&#91;'Python Programming', 'Project Management'], dependents={'wife': 'Jane', 'children': &#91;'Alice', 'Bob']} ) pprint(e.to_dict())<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>Output:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>{'dependents': {'children': &#91;'Alice', 'Bob'], 'wife': 'Jane'}, 'name': 'John', 'skills': &#91;'Python Programming', 'Project Management']}<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>The following shows the complete code:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>from pprint import pprint class DictMixin: def to_dict(self): return self._traverse_dict(self.__dict__) def _traverse_dict(self, attributes): result = {} for key, value in attributes.items(): result&#91;key] = self._traverse(key, value) return result def _traverse(self, key, value): if isinstance(value, DictMixin): return value.to_dict() elif isinstance(value, dict): return self._traverse_dict(value) elif isinstance(value, list): return &#91;self._traverse(key, v) for v in value] elif hasattr(value, '__dict__'): return self._traverse_dict(value.__dict__) else: return value class Person: def __init__(self, name): self.name = name class Employee(DictMixin, Person): def __init__(self, name, skills, dependents): super().__init__(name) self.skills = skills self.dependents = dependents if __name__ == '__main__': e = Employee( name='John', skills=&#91;'Python Programming', 'Project Management'], dependents={'wife': 'Jane', 'children': &#91;'Alice', 'Bob']} ) pprint(e.to_dict())<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Compose multiple mixin classes<\/h2>\n\n\n\n<p>Suppose you want to convert the\u00a0<code>Employee<\/code>\u2018s object to JSON. To do that, you can first define a new mixin class that use the\u00a0<code>json<\/code>\u00a0standard module:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>import json class JSONMixin: def to_json(self): return json.dumps(self.to_dict())<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>And then change the\u00a0<code>Employee<\/code>\u00a0class so that it inherits the\u00a0<code>JSONMixin<\/code>\u00a0class:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>class Employee(DictMixin, JSONMixin, Person): def __init__(self, name, skills, dependents): super().__init__(name) self.skills = skills self.dependents = dependents<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>The following creates a new instance of the\u00a0<code>Employee<\/code>\u00a0class and converts it to a dictionary and json:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>if __name__ == '__main__': e = Employee( name='John', skills=&#91;'Python Programming''Project Management'], dependents={'wife': 'Jane', 'children': &#91;'Alice', 'Bob']} ) pprint(e.to_dict()) print(e.to_json())<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>Output:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>{'dependents': {'children': &#91;'Alice', 'Bob'], 'wife': 'Jane'}, 'name': 'John', 'skills': &#91;'Python ProgrammingProject Management']} {\"name\": \"John\", \"skills\": &#91;\"Python ProgrammingProject Management\"], \"dependents\": {\"wife\": \"Jane\", \"children\": &#91;\"Alice\", \"Bob\"]}}<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>The following shows the complete code:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>import json from pprint import pprint class DictMixin: def to_dict(self): return self._traverse_dict(self.__dict__) def _traverse_dict(self, attributes): result = {} for key, value in attributes.items(): result&#91;key] = self._traverse(key, value) return result def _traverse(self, key, value): if isinstance(value, DictMixin): return value.to_dict() elif isinstance(value, dict): return self._traverse_dict(value) elif isinstance(value, list): return &#91;self._traverse(key, v) for v in value] elif hasattr(value, '__dict__'): return self._traverse_dict(value.__dict__) else: return value class JSONMixin: def to_json(self): return json.dumps(self.to_dict()) class Person: def __init__(self, name): self.name = name class Employee(DictMixin, JSONMixin, Person): def __init__(self, name, skills, dependents): super().__init__(name) self.skills = skills self.dependents = dependents if __name__ == '__main__': e = Employee( name='John', skills=&#91;'Python Programming''Project Management'], dependents={'wife': 'Jane', 'children': &#91;'Alice', 'Bob']} ) pprint(e.to_dict()) print(e.to_json())<\/code><\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Summary: in this tutorial, you\u2019ll learn about Python mixin classes and how to use them to make the code reusable. What is a mixin in Python A mixin is a\u00a0class\u00a0that provides method implementations for reuse by multiple related child classes. However, the inheritance is not implying an is-a relationship. A mixin doesn\u2019t define a new [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[31],"tags":[],"class_list":["post-207","post","type-post","status-publish","format-standard","hentry","category-7-multiple-inheritance-descriptors"],"_links":{"self":[{"href":"https:\/\/learnpython.elegantwallp.com\/wp-json\/wp\/v2\/posts\/207","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/learnpython.elegantwallp.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/learnpython.elegantwallp.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/learnpython.elegantwallp.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/learnpython.elegantwallp.com\/wp-json\/wp\/v2\/comments?post=207"}],"version-history":[{"count":1,"href":"https:\/\/learnpython.elegantwallp.com\/wp-json\/wp\/v2\/posts\/207\/revisions"}],"predecessor-version":[{"id":208,"href":"https:\/\/learnpython.elegantwallp.com\/wp-json\/wp\/v2\/posts\/207\/revisions\/208"}],"wp:attachment":[{"href":"https:\/\/learnpython.elegantwallp.com\/wp-json\/wp\/v2\/media?parent=207"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/learnpython.elegantwallp.com\/wp-json\/wp\/v2\/categories?post=207"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/learnpython.elegantwallp.com\/wp-json\/wp\/v2\/tags?post=207"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}