From 615cd66a873853f335177ec8b307c35be17d4b36 Mon Sep 17 00:00:00 2001 From: Simeon Simeonov Date: Wed, 21 Sep 2022 15:38:37 +0200 Subject: Add notebooks/python/python_oo.ipynb and update notebooks/sqlalchemy/sqlalchemy.ipynb --- notebooks/python/python_oo.ipynb | 274 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 274 insertions(+) create mode 100644 notebooks/python/python_oo.ipynb (limited to 'notebooks/python') diff --git a/notebooks/python/python_oo.ipynb b/notebooks/python/python_oo.ipynb new file mode 100644 index 0000000..0b33a09 --- /dev/null +++ b/notebooks/python/python_oo.ipynb @@ -0,0 +1,274 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "2612fc97-1e84-4cc1-bd55-4cc58dbd5074", + "metadata": {}, + "source": [ + "# Introduction to object-oriented programming in Python\n", + "\n", + "Simeon Simeonov @ Statnett" + ] + }, + { + "cell_type": "markdown", + "id": "84139fa9-733e-4871-a2f9-920f6e7c4911", + "metadata": {}, + "source": [ + "# Goals\n", + "\n", + "- present the Python programming language in a different way than [https://docs.python.org](https://docs.python.org)\n", + "\n", + "- avoid information overload\n", + "\n", + "- use examples and interaction rather than documents and slides\n", + "\n", + "\n", + "## Target audience\n", + "\n", + "- beginner Python programmers\n", + "\n", + "- analysts using Python as a tool" + ] + }, + { + "cell_type": "markdown", + "id": "d6d3d0e7-c1d5-4119-940e-0f94ee7542ec", + "metadata": {}, + "source": [ + "# What is object-oriented programming?\n", + "\n", + "Object-oriented programming does **not** mean using an object-oriented programming language.\n", + "\n", + "It is rather a programming paradigm based on the concept of object, as well as on some general principles and best practices aiming at:\n", + "\n", + "- improving readability\n", + "\n", + "- improving re-usability\n", + "\n", + "- improving modularity\n", + "\n", + "- providing foundation for a more intuitive design" + ] + }, + { + "cell_type": "markdown", + "id": "ad19da5c-3c21-4130-9225-d8f7cb2a7f40", + "metadata": {}, + "source": [ + "# General principles\n", + "\n", + "The following four concepts / principles are presented in most object-oriented programming books:\n", + "\n", + "- separate and hide \"private\" details from the outside world and / or child (inheriting) functionality (*encapsulation*) - supports *separation of concerns*\n", + "\n", + "- separate the interface from its implementation (*abstraction*)\n", + "\n", + "- inherit and extend / adapt existing functionality, through \"is-a\" relationship hierarchy (*inheritance*)\n", + "\n", + "- execute different code / functionality based on the object's place in the hierarchy (polymorphism)" + ] + }, + { + "cell_type": "markdown", + "id": "22b2bf7e-764b-44c8-a9fd-83733319fc6e", + "metadata": {}, + "source": [ + "# Building blocks and definitions\n", + "\n", + "**Note:** \"Lacking universally accepted terminology to talk about classes, I will make occasional use of Smalltalk and C++ terms.\" - The Python tutorial [https://docs.python.org](https://docs.python.org)\n", + "\n", + "When talking about object-oriented programming, the following building blocks are involved:\n", + "\n", + "- class - a blueprint / template for creating objects\n", + "\n", + "- object - an instance of a class that may contain its own attributes as well as references to its class' attributes\n", + "\n", + "- attribute - variable, property, function defined in the class and present in its instances\n", + "\n", + "- class variable - attribute of which a single copy exists, regardless of how many instances of the class exist\n", + "\n", + "- object / instance variable - attribute for which each instantiated object of the class has a separate copy, or instance\n", + "\n", + "- method - member function - function that is an attribute" + ] + }, + { + "cell_type": "markdown", + "id": "9e15c843-f65b-4bd3-a536-e0217b3947f8", + "metadata": {}, + "source": [ + "# The object-oriented world of Python\n", + "\n", + "Some additional concepts and definitions are introduced in Python, as well as in some other programming languages:\n", + "\n", + "- metaclass - a class whose instances are classes\n", + "\n", + "- property - attribute that provides a flexible mechanism to read, write, or compute the value of a \"private\" attribute\n", + "\n", + "- type - old C object-oriented term, now (in Python 3) considered to be the same as class\n", + "\n", + "As is true for modules, classes partake of the dynamic nature of Python: they are created at runtime, and can be modified further after creation.\n", + "\n", + "Each object in Python has an ID - an integer which is guaranteed to be unique and constant for this object during its lifetime.\n", + "Two objects with non-overlapping lifetimes may have the same *id()* value. In *CPython* this is the address of the object in memory.\n", + "\n", + "Python has automatic memory management using reference counting. When an object no longer has\n", + "any references, the garbage collector kicks inn and removes the object from memory." + ] + }, + { + "cell_type": "markdown", + "id": "d647b1ad-948d-495d-bb30-15761b806354", + "metadata": {}, + "source": [ + "# Example1\n", + "\n", + "We will create and extend classes for representing points and vectors in 2D space" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "391e816e-c53b-454b-9e9f-3587234f1fea", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2:8\n", + "2:8\n", + "2\n", + "2\n" + ] + }, + { + "ename": "AttributeError", + "evalue": "'Point' object has no attribute '__y'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn [7], line 69\u001b[0m\n\u001b[1;32m 66\u001b[0m \u001b[38;5;66;03m# we \"should not\" be accessing private and protected attributes directly\u001b[39;00m\n\u001b[1;32m 67\u001b[0m \u001b[38;5;28mprint\u001b[39m(my_first_point\u001b[38;5;241m.\u001b[39m_x)\n\u001b[0;32m---> 69\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[43mmy_first_point\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m__y\u001b[49m)\n", + "\u001b[0;31mAttributeError\u001b[0m: 'Point' object has no attribute '__y'" + ] + } + ], + "source": [ + "class Point:\n", + " \"\"\"Basic class for representing points in 2D space\"\"\"\n", + "\n", + " def __init__(self, x: int, y: int):\n", + " \"\"\"\n", + " Called after the instance has been created (by __new__()), but before\n", + " it is returned to the caller. The arguments are those passed to the\n", + " class constructor expression.\n", + " \n", + " If a base class has an __init__() method, the derived class’s\n", + " __init__() method, if any, must explicitly call it to ensure proper\n", + " initialization of the base class part of the instance;\n", + " for example: super().__init__([args...]).\n", + " \"\"\"\n", + " self._x = x # _ indicates \"protected\" attribute\n", + " self.__y = y # not a typo: __ indicates \"private\" attribute\n", + "\n", + " def __repr__(self):\n", + " \"\"\"\n", + " Called by the repr() built-in function to compute the “official”\n", + " string representation of an object. If at all possible, this should\n", + " look like a valid Python expression that could be used to recreate an\n", + " object with the same value (given an appropriate environment). If this\n", + " is not possible, a string of the form <...some useful description...>\n", + " should be returned. The return value must be a string object.\n", + " \n", + " If a class defines __repr__() but not __str__(), then __repr__() is\n", + " also used when an “informal” string representation of instances of\n", + " that class is required. This is typically used for debugging, so it is\n", + " important that the representation is information-rich and unambiguous.\n", + " \"\"\"\n", + " return f\"\"\n", + "\n", + " def __str__(self):\n", + " \"\"\"\n", + " Called by str(object) and the built-in functions format() and print()\n", + " to compute the “informal” or nicely printable string representation of\n", + " an object. The return value must be a string object.\n", + "\n", + " This method differs from object.__repr__() in that there is no\n", + " expectation that __str__() return a valid Python expression: a more\n", + " convenient or concise representation can be used.\n", + "\n", + " The default implementation defined by the built-in type object calls\n", + " object.__repr__().\n", + " \"\"\"\n", + " return f\"{self._x}:{self.__y}\"\n", + "\n", + " @property\n", + " def x(self) -> int:\n", + " \"\"\"getter property x\"\"\"\n", + " return self._x\n", + "\n", + " @property\n", + " def y(self) -> int:\n", + " \"\"\"getter property y\"\"\"\n", + " return self.__y\n", + "\n", + "\n", + "my_first_point = Point(2, 8)\n", + "\n", + "print(f\"{my_first_point}\")\n", + "print(f\"{my_first_point}\")\n", + "print(my_first_point.x)\n", + "\n", + "# we \"should not\" be accessing private and protected attributes directly\n", + "print(my_first_point._x)\n", + "\n", + "print(my_first_point.__y) # will not work\n", + "# Out: AttributeError: 'Point' object has no attribute '__y'\n", + "\n", + "# will work, but should not be used by a sane programmer:\n", + "# print(my_first_point._Point__y)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e82feefb-025d-4cbb-a8ac-ddc3cc01269c", + "metadata": {}, + "outputs": [], + "source": [ + "class Vector:\n", + " \"\"\"Basic class for representing vectors in 2D space\"\"\"\n", + "\n", + " def __init__(self, start: Point, end: Point):\n", + " self._start = start\n", + " self._end = end\n", + "\n", + " def __str__(self):\n", + " return f\"{self._start} -> {self._end}\"\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.10" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} -- cgit v1.3