{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "# Software Entwicklung \n",
    "\n",
    "## Kapitel 5: Module und Pakete\n",
    "\n",
    "Die Sichtbarkeit von programmiersprachlichen Objekten wie Funktionen oder globalen Variablen\n",
    "ist bei Python auf die jeweilige Programmdatei beschränkt. Eine solche Python-Datei wird auch als\n",
    "*Modul* bezeichnet. Sie spannt einen *Namensraum* auf, d.h. innerhalb des Moduls existieren (globale)\n",
    "Bezeichner nur einmal; außerhalb der Datei in anderen Modulen können Funktionen etc. gleichen\n",
    "Namens existieren, ohne dass es zu Konflikten kommt."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Python bietet jedoch die Möglichkeit, größere Programme auf mehrere Module aufzuteilen und\n",
    "so die damit verbundene Komplexität beherrschbar zu gestalten. Typischerweise stützt sich dabei ein\n",
    "*Top-Level-Modul* auf weitere nachgeordnete Module, die z.B. Funktionen oder\n",
    "Datentypen definieren und bereitstellen.\n",
    "\n",
    "![Module](../img/module.png \"Module\")\n",
    "\n",
    "Python selbst liefert bereits eine Reihe von Modulen mit aus, die die Möglichkeiten der Sprache \n",
    "erweitern. Die Summe aller mitgelieferten Module wird als *Standard-Bibliothek* bezeichnet.\n",
    "\n",
    "Die Standard-Bibliothek ist so umfangreich, dass eine vollumfängliche Behandlung bereits im Ansatz\n",
    "zum Scheitern verurteilt wäre. Im Folgenden werden lediglich ausgewählte Module als Beispiel\n",
    "aufgeführt. Eine vollständige Übersicht bietet die offizielle\n",
    "[Dokumentation](https://docs.python.org/3/library/)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### 5.1 Import von Modulen\n",
    "\n",
    "Da die Sichtbarkeit von programmiersprachlichen Objekten normalerweise an der Dateigrenze endet,\n",
    "müssen die nachgeordneten Module in das übergeordnete Modul *importiert* werden. Sollen\n",
    "Beispielsweise Funktionen des Standard-Moduls <code>math</code> verwendet werden,\n",
    "so können diese folgendermaßen zugänglich gemacht werden."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "import math\n",
    "\n",
    "zahl = float(input(\"Zahl: \"))\n",
    "wurzel = math.sqrt(zahl)\n",
    "print(f\"Die Wurzel von {zahl} ist {wurzel}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Um Konflikte bei gleichnamigen Objekten zu vermeiden, muss für den Zugriff in diesem Fall stets der\n",
    "komplette Pfad zum importierten Objekt angegeben werden. Alle im Modul definierten Funktionen\n",
    "sind so zugänglich. Im Falle von <code>math</code> sind dies die wesentlichen mathematischen Funktionen\n",
    "wie z.B.\n",
    "\n",
    "* Sinus <code>sin</code>\n",
    "* Cosinus <code>cos</code>\n",
    "* Exponentialfunktion <code>exp</code>\n",
    "* Logarithmus <code>log</code>\n",
    "* Wurzel <code>sqrt</code>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "sowie einige mathematische Konstante wie z.B.\n",
    "\n",
    "* <code>pi</code>\n",
    "* <code>e</code>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    },
    "slideshow": {
     "slide_type": "-"
    }
   },
   "outputs": [],
   "source": [
    "import math\n",
    "\n",
    "print(math.cos(math.pi))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Beim Import kann dem Modul auch ein abweichender Name gegeben werden, um z.B. lange\n",
    "Modulnamen abzukürzen. Im nachfolgenden Beispiel das Modul <code>datetime</code> unter dem\n",
    "neuen Namen <code>dt</code> importiert und anschließend der im Modul definierte Datentyp\n",
    "<code>date</code> verwendet, der die Funktion <code>today</code> bereitstellt."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "import datetime as dt\n",
    "\n",
    "print(dt.date.today())\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### 5.2 Einbinden von Modulinhalten\n",
    "\n",
    "Neben dem Importieren von fremden Modulen können deren Inhalte auch selektiv mittels\n",
    "\n",
    "<code>from \\< module \\> import \\< Bezeichner \\> </code>\n",
    "\n",
    "in den eigenen Namensraum eingebunden werden. Die Angabe eines vollständigen Pfads entfällt dann."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "from math import sin, pi\n",
    "\n",
    "print(sin(pi))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Bei dieser Art der Einbindung können die eingebundenen Objekte umbenannt werden."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "from math import sin as sinus, pi\n",
    "\n",
    "print(sinus(pi))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    },
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Bei der Einbettung in den eigenen Adressraum kann es zu Konflikten mit im eigenen Modul definierten\n",
    "Funktionen o.ä. kommen. Da Python Module beim Importieren ausführt und die darin enthaltenen Definitionen \n",
    "verarbeitet, können die so definierten Bezeichner durch eine erneute Definition verändert werden."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "from math import sin\n",
    "\n",
    "def sin(x):\n",
    "    return x\n",
    "\n",
    "#from math import sin\n",
    "\n",
    "print(sin(1))"
   ]
  }
 ],
 "metadata": {
  "celltoolbar": "Slideshow",
  "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.9.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
