From a5ad1fd2ab1abba086148d1d676426af3d9a58a9 Mon Sep 17 00:00:00 2001 From: Simeon Simeonov Date: Fri, 28 Oct 2022 13:43:55 +0200 Subject: Update python_oo.ipynb --- notebooks/python/python_oo.ipynb | 146 ++++++++++++++++++++++++++++++++------- 1 file changed, 121 insertions(+), 25 deletions(-) (limited to 'notebooks/python/python_oo.ipynb') diff --git a/notebooks/python/python_oo.ipynb b/notebooks/python/python_oo.ipynb index 2440efb..df5907b 100644 --- a/notebooks/python/python_oo.ipynb +++ b/notebooks/python/python_oo.ipynb @@ -208,7 +208,7 @@ }, { "cell_type": "code", - "execution_count": 287, + "execution_count": 70, "id": "391e816e-c53b-454b-9e9f-3587234f1fea", "metadata": {}, "outputs": [ @@ -306,7 +306,7 @@ }, { "cell_type": "code", - "execution_count": 288, + "execution_count": 71, "id": "e82feefb-025d-4cbb-a8ac-ddc3cc01269c", "metadata": {}, "outputs": [ @@ -389,7 +389,7 @@ }, { "cell_type": "code", - "execution_count": 289, + "execution_count": 72, "id": "71a90ec6-3cc0-441e-a866-c2c2b9984559", "metadata": {}, "outputs": [ @@ -503,7 +503,7 @@ }, { "cell_type": "code", - "execution_count": 290, + "execution_count": 73, "id": "a4d2735d-d167-4f43-ad55-cb3d13ece2dc", "metadata": {}, "outputs": [ @@ -546,7 +546,7 @@ }, { "cell_type": "code", - "execution_count": 291, + "execution_count": 74, "id": "a6ead5e6-e987-4bda-bf48-30f91877278d", "metadata": {}, "outputs": [ @@ -605,7 +605,7 @@ }, { "cell_type": "code", - "execution_count": 292, + "execution_count": 75, "id": "11f6a3fb-64d7-40a9-a130-27548ec4b802", "metadata": {}, "outputs": [ @@ -683,7 +683,7 @@ }, { "cell_type": "code", - "execution_count": 293, + "execution_count": 76, "id": "c345a69f-02da-40e7-bb37-c0511b6af096", "metadata": {}, "outputs": [ @@ -774,7 +774,7 @@ }, { "cell_type": "code", - "execution_count": 294, + "execution_count": 77, "id": "44d47e1c-1a06-4577-8db6-6ec78ce5cef8", "metadata": {}, "outputs": [ @@ -815,7 +815,8 @@ " | \n", " | weight\n", " | getter property weight\n", - "\n" + "\n", + "(, , , )\n" ] } ], @@ -903,7 +904,8 @@ "cow1 = Cow(350)\n", "cow1.make_a_sound()\n", "tiger_shark1 = TigerShark(80)\n", - "help(TigerShark)" + "help(TigerShark)\n", + "print(TigerShark.__mro__) # more elegant will be to use the inspect module: inspect.getmro(TigerShark)" ] }, { @@ -917,7 +919,7 @@ "\n", "- how do we handle the growing amount of params we have to send to `super()`?\n", "\n", - "- how do insert functionality that does not necessarily follow the structure of our hierarchy. F.i predator functionality?\n", + "- how to insert functionality that does not necessarily follow the structure of our hierarchy. F.i predator functionality?\n", "\n", "\n", "## Possible solutions\n", @@ -944,19 +946,9 @@ "A mixin class is like an interface in Java, hence the phrase 'implements X functionality' should fit in the mixin description.\n" ] }, - { - "cell_type": "markdown", - "id": "35b3a8eb-e7b0-4181-822f-923a74a7ab27", - "metadata": {}, - "source": [ - "# Example 3\n", - "\n", - "Demonstrates the use of mixins." - ] - }, { "cell_type": "code", - "execution_count": 295, + "execution_count": 78, "id": "e6076925-75f0-456c-aed5-7db0a24a67a1", "metadata": {}, "outputs": [ @@ -1048,12 +1040,20 @@ "In other words, you don't get to choose who your `super()` is going to call, your children get to choose. \n", "Single inheritance is just a special case and simplification of the general rule.\n", "\n", - "Python>=2.3 uses the [C3 Method Resolution Order (MRO)](https://www.python.org/download/releases/2.3/mro/), replacing the old *depth first and then left to right* in Python<=2.2." + "Python>=2.3 uses the [C3 Method Resolution Order (MRO)](https://www.python.org/download/releases/2.3/mro/), replacing the old *depth first and then left to right* in Python<=2.2.\n", + "\n", + "The *MRO* is the set of rules that construct the linearization. In the Python literature, the idiom \"the MRO of C\" is also used as a synonymous for the linearization of the class C.\n", + "\n", + "MRO is monotonic when the following is true: if C1 precedes C2 in the linearization of C, then C1 precedes C2 in the linearization of any subclass of C.\n", + "\n", + "Not all classes admit a linearization. There are cases, in complicated hierarchies, where it is not possible to derive a class such that its linearization respects all the desired properties. \n", + "`TypeError: Cannot create a consistent method resolution order (MRO) for bases X, Y` is raised then.\n", + "\n" ] }, { "cell_type": "code", - "execution_count": 296, + "execution_count": 79, "id": "cf79617a-95d2-48f2-be66-fa1fa34e4e04", "metadata": {}, "outputs": [ @@ -1105,6 +1105,98 @@ "print(f\"Simeon's MRO: {Simeon.__mro__}\")" ] }, + { + "cell_type": "code", + "execution_count": 80, + "id": "95a1d0cc-0006-4ddc-b08d-d0b8b02acfba", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Getting data using a proprietary driver, from a proprietary high tech & mega secured cluster while being charged 100USD per MB\n", + "Extracting production plans from data\n", + "some magic is happening here...\n", + "{}\n" + ] + } + ], + "source": [ + "# Real multiple inheritance\n", + "\n", + "# Inspired by Raymond Hettinger - \"Super considered super!\" - PyCon 2015\n", + "import json\n", + "\n", + "\n", + "class ConnectionManager:\n", + " \"\"\"Handles connection and extraction of raw data\"\"\"\n", + "\n", + " def get_data(self, *args, **kwargs):\n", + " \"\"\"difficult and expensive to test functionality here\"\"\"\n", + " print(\n", + " \"Getting data using a proprietary driver, from a proprietary high \"\n", + " \"tech & mega secured cluster while being charged 100USD per MB\"\n", + " )\n", + " \n", + " def extract_production_plans(self, *args, **kwargs):\n", + " print(\"Extracting production plans from data\")\n", + "\n", + "\n", + "class CoolTSPreprocessor(ConnectionManager):\n", + " \"\"\"Produces JSON content for production plans\"\"\"\n", + " \n", + " def to_json(self, **kwargs):\n", + " # super().get_data(**kwargs)\n", + " self.get_data(**kwargs)\n", + " prod_plans = self.extract_production_plans(**kwargs)\n", + " return json.dumps(self.__do_some_magic(prod_plans), indent=kwargs.get(\"indent\", 2))\n", + " \n", + " def __do_some_magic(self, prod_plans):\n", + " processed_plans = {}\n", + " print(\"some magic is happening here...\")\n", + " return processed_plans\n", + "\n", + "\n", + "class MockConnectionManager(ConnectionManager):\n", + " \"\"\"\n", + " Mock connection manager using a static data without really connecting to a real cluster\n", + " \"\"\"\n", + "\n", + " def get_data(self, *args, **kwargs):\n", + " print(\"Using mock data\")\n", + "\n", + "\n", + "cool_ts_proprocessor = CoolTSPreprocessor()\n", + "print(cool_ts_proprocessor.to_json(indent=4))" + ] + }, + { + "cell_type": "code", + "execution_count": 81, + "id": "38066107-0190-4383-ba14-a4e9cd454a9c", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Using mock data\n", + "Extracting production plans from data\n", + "some magic is happening here...\n", + "(, , , , )\n" + ] + } + ], + "source": [ + "class MockedButStillCoolTSPreprocessor(CoolTSPreprocessor, MockConnectionManager):\n", + " pass\n", + "\n", + "mocked_but_still_cool_ts_preprocessor = MockedButStillCoolTSPreprocessor()\n", + "mocked_but_still_cool_ts_preprocessor.to_json(indent=4)\n", + "print(MockedButStillCoolTSPreprocessor.__mro__)" + ] + }, { "cell_type": "markdown", "id": "540de317-ba77-4f5c-97ba-f1c0bec071fb", @@ -1124,7 +1216,11 @@ "\n", " - `__hash__`\n", " \n", - " - ...\n" + " - ...\n", + "\n", + "- [Raymond Hettinger - Super considered super! - PyCon 2015](https://www.youtube.com/watch?v=EiOglTERPEo)\n", + "\n", + "- [C3 Method Resolution Order (MRO)](https://www.python.org/download/releases/2.3/mro/) - for the real enthusiasts" ] } ], -- cgit v1.3