diff --git a/002-basic-control-structures/Basic control structures II.ipynb b/002-basic-control-structures/Basic control structures II.ipynb index f8b129e..303f131 100644 --- a/002-basic-control-structures/Basic control structures II.ipynb +++ b/002-basic-control-structures/Basic control structures II.ipynb @@ -2212,7 +2212,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": { "hideCode": false, "hidePrompt": false @@ -2235,12 +2235,187 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": { - "hideCode": false, - "hidePrompt": false - }, - "outputs": [], + "execution_count": 4, + "metadata": { + "hideCode": false, + "hidePrompt": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2\n", + "3\n", + "5\n", + "7\n", + "11\n", + "13\n", + "17\n", + "19\n", + "23\n", + "29\n", + "31\n", + "37\n", + "41\n", + "43\n", + "47\n", + "53\n", + "59\n", + "61\n", + "67\n", + "71\n", + "73\n", + "79\n", + "83\n", + "89\n", + "97\n", + "101\n", + "103\n", + "107\n", + "109\n", + "113\n", + "127\n", + "131\n", + "137\n", + "139\n", + "149\n", + "151\n", + "157\n", + "163\n", + "167\n", + "173\n", + "179\n", + "181\n", + "191\n", + "193\n", + "197\n", + "199\n", + "211\n", + "223\n", + "227\n", + "229\n", + "233\n", + "239\n", + "241\n", + "251\n", + "257\n", + "263\n", + "269\n", + "271\n", + "277\n", + "281\n", + "283\n", + "293\n", + "307\n", + "311\n", + "313\n", + "317\n", + "331\n", + "337\n", + "347\n", + "349\n", + "353\n", + "359\n", + "367\n", + "373\n", + "379\n", + "383\n", + "389\n", + "397\n", + "401\n", + "409\n", + "419\n", + "421\n", + "431\n", + "433\n", + "439\n", + "443\n", + "449\n", + "457\n", + "461\n", + "463\n", + "467\n", + "479\n", + "487\n", + "491\n", + "499\n", + "503\n", + "509\n", + "521\n", + "523\n", + "541\n", + "547\n", + "557\n", + "563\n", + "569\n", + "571\n", + "577\n", + "587\n", + "593\n", + "599\n", + "601\n", + "607\n", + "613\n", + "617\n", + "619\n", + "631\n", + "641\n", + "643\n", + "647\n", + "653\n", + "659\n", + "661\n", + "673\n", + "677\n", + "683\n", + "691\n", + "701\n", + "709\n", + "719\n", + "727\n", + "733\n", + "739\n", + "743\n", + "751\n", + "757\n", + "761\n", + "769\n", + "773\n", + "787\n", + "797\n", + "809\n", + "811\n", + "821\n", + "823\n", + "827\n", + "829\n", + "839\n", + "853\n", + "857\n", + "859\n", + "863\n", + "877\n", + "881\n", + "883\n", + "887\n", + "907\n", + "911\n", + "919\n", + "929\n", + "937\n", + "941\n", + "947\n", + "953\n", + "967\n", + "971\n", + "977\n", + "983\n", + "991\n", + "997\n" + ] + } + ], "source": [ "# Print all the primes below 1000\n", "for prime in primes():\n", @@ -2261,9 +2436,9 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": { - "hideCode": true, + "hideCode": false, "hideOutput": false, "hidePrompt": false }, diff --git a/020-patterns/Solid Ideas.ipynb b/020-patterns/Solid Ideas.ipynb index db7b6af..a13d514 100644 --- a/020-patterns/Solid Ideas.ipynb +++ b/020-patterns/Solid Ideas.ipynb @@ -377,7 +377,7 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 2, "metadata": {}, "outputs": [ { @@ -387,7 +387,7 @@ "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0;34m...\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 10\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 11\u001b[0;31m \u001b[0mDolfin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0;34m...\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 10\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 11\u001b[0;31m \u001b[0mDolfin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mTypeError\u001b[0m: Can't instantiate abstract class Dolfin with abstract methods walk" ] } @@ -406,6 +406,39 @@ "Dolfin()" ] }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "ename": "NotImplementedError", + "evalue": "This animal cannot walk", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNotImplementedError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 10\u001b[0m \u001b[0;34m...\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 11\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 12\u001b[0;31m \u001b[0mDolfin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mwalk\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m\u001b[0m in \u001b[0;36mwalk\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mclass\u001b[0m \u001b[0mAnimal\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mwalk\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mNotImplementedError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"This animal cannot walk\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;32mclass\u001b[0m \u001b[0mMonkey\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mAnimal\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mNotImplementedError\u001b[0m: This animal cannot walk" + ] + } + ], + "source": [ + "class Animal:\n", + " def walk(self):\n", + " raise NotImplementedError(\"This animal cannot walk\")\n", + " \n", + "class Monkey(Animal):\n", + " def walk(self):\n", + " ...\n", + " \n", + "class Dolfin(Animal):\n", + " ...\n", + " \n", + "Dolfin().walk()" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -436,7 +469,7 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ @@ -459,7 +492,7 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 9, "metadata": {}, "outputs": [], "source": [ @@ -629,10 +662,105 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 16, "metadata": {}, - "outputs": [], - "source": [] + "outputs": [ + { + "data": { + "text/plain": [ + "['left-front',\n", + " 'left-middle-front',\n", + " 'left-middle-back',\n", + " 'left-back',\n", + " 'right-front',\n", + " 'right-middle-front',\n", + " 'right-middle-back',\n", + " 'right-back',\n", + " 'left-back',\n", + " 'right-back',\n", + " 'left-front',\n", + " 'right-front',\n", + " 'left-back',\n", + " 'right-back',\n", + " 'left-front',\n", + " 'right-front']" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "class Animal:\n", + " name = 'Unknown'\n", + " \n", + " # OCP: Even if our animal doesn't have legs, it will nonetheless have a legs\n", + " # list, if this constructor gets called. If users of the Animal class use this\n", + " # directly, they could get silent bugs by looking at e.g. dolphin.legs\n", + " def __init__(self):\n", + " self.legs = ['left-back', 'right-back', 'left-front', 'right-front']\n", + " \n", + " # ISP: not all animals have legs, why are we requiring them to have leg-names?\n", + " @abc.abstractmethod\n", + " def get_leg_names(self):\n", + " pass\n", + "\n", + "class Giraffe(Animal):\n", + " name = 'Giraffe'\n", + " \n", + " def get_leg_names(self):\n", + " return ', '.join(self.legs)\n", + " \n", + "class Tarantula(Animal):\n", + " name = 'Tarantula'\n", + " \n", + " def __init__(self):\n", + " self.legs = [\n", + " 'left-front', 'left-middle-front', 'left-middle-back', 'left-back',\n", + " 'right-front', 'right-middle-front', 'right-middle-back', 'right-back'\n", + " ]\n", + " \n", + " def get_leg_names(self):\n", + " return ', '.join(self.legs)\n", + "\n", + "class Butterfly(Animal):\n", + " name = 'Butterfly'\n", + " has_transformed = None\n", + " \n", + " # LSP: we are expecting this to initialize whether\n", + " # our butterfly is still a caterpillar or not, but that's\n", + " # not something that users of the superclass will do...\n", + " def set_is_transformed(self, transformed):\n", + " self.has_transformed = transformed\n", + " \n", + " def get_leg_names(self):\n", + " return ['leg {n}' for n in range(6 if self.has_transformed else 16)]\n", + "\n", + "class Zoo:\n", + " def __init__(self):\n", + " # DIP: bit of an extreme example, but rather than saying which animals\n", + " # are in our zoo, or passing a creator function, the constructor will\n", + " # only ever work exactly with these three animals.\n", + " self.animals = [\n", + " Tarantula(),\n", + " Butterfly(),\n", + " Giraffe()\n", + " ]\n", + " \n", + " # SRP: we are baking in how animals are shown to our domain model class\n", + " # (might also notice this links to separation of layers in DDD/MVC)\n", + " def print_animals():\n", + " for animal in self.animals:\n", + " print(f'A {animal.name} has {len(animal.get_leg_names())}')\n", + " \n", + "zoo = Zoo()\n", + "\n", + "# LOD: not only are we baking in the assumption that animals have legs,\n", + "# we're baking in the way that's stored - note that this has gone wrong for\n", + "# Butterflies who do not use the legs list\n", + "sum((zoo.animals[i].legs for i in range(3)), [])" + ] } ], "metadata": {