{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Python Grundlagen\n",
    "- Dynamisch typisierte Sprache\n",
    "- Statt geschweifter Klammern für Codeblöcke (Funktionen, Schleifen) wird Code mit vier Leerzeichen (pro Hierarchieebene) eingerückt\n",
    "- Die meisten Editoren ersetzen Tab automatisch durch vier Leerzeichen\n",
    "- Kommentare beginnen mit Raute #"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Grundlegende Datentypen\n",
    "Zahlentypen (int/float) sind größtenteils äquivalent zu Java. Strings können mit doppelten oder einfachen Anführungszeichen deklariert werden."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = 2*2.0\n",
    "b = 5\n",
    "\n",
    "print(a + b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a += 1\n",
    "# a++ existiert nicht\n",
    "\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "2**4"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "2/4"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "text1 = 'Hallo '\n",
    "text2 = \"Welt\"\n",
    "\n",
    "print (text1 + text2)\n",
    "\n",
    "# Andere Datentypen müssen explizit in Strings konvertiert werden,\n",
    "# wenn sie an einen String angehängt werden sollen.\n",
    "print(text1 + str(1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "float('1')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "float(1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*None* entspricht *null* in Java."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "myvar = None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(myvar)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "if myvar is None:\n",
    "    print('x ist nicht definiert')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Listen\n",
    "Listen werden mit eckigen Klammern oder list() initialisiert."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "l = [1,2,3,3]\n",
    "l.append(4)\n",
    "\n",
    "print(l)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Vorsicht bei der Kombination von Listen. append hängt die übergebene Variable als einzelnen Listeneintrag an die Liste an."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "l.append([5, 6])\n",
    "\n",
    "print(l)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Zur Kombination von zwei Listen wird der +-Operator verwendet."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "l2 = l + [5,6]\n",
    "\n",
    "print(l2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Mengen\n",
    "Mengen können mit geschweiften Klammern oder set() initialisiert werden."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "s = {1,2,3,3}\n",
    "s2 = set([2,3,4,5])\n",
    "\n",
    "print(s)\n",
    "print(s.intersection(s2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "s.add(9)\n",
    "s.remove(2)\n",
    "s"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Mit list() und set() können die Typen auch ineinander konvertiert werden."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "list(s)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "set([1,2,3])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Ranges\n",
    "Auflistung von Zahlen, werden z.Bsp. für for-Schleifen mit Index verwendet."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "for i in range(5):\n",
    "    print(i)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Tupel\n",
    "Für sortierete Werte mit fester Komponentenanzahl und fester Bedeutung für jeden Eintrag."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "essen = 'Chili'\n",
    "preis = 2.51\n",
    "boneintrag = (essen, preis)\n",
    "\n",
    "print(boneintrag)\n",
    "print(boneintrag[0])\n",
    "print(boneintrag[1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(essen2, preis2) = boneintrag\n",
    "\n",
    "print(essen2)\n",
    "print(preis2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Klammern können oft weggelassen werden"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "boneintrag = essen, preis\n",
    "essen2, preis2 = boneintrag\n",
    "\n",
    "print(boneintrag)\n",
    "print(essen2)\n",
    "print(preis2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Dictionaries\n",
    "Äquivalent zu Maps."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "d = {'Chili': 1.90, 'Penne': 2.50}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "d.keys()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "d.values()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "for key, val in d.items():\n",
    "    print('{}: {}'.format(key, val))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "d['Chili']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "d['Burger'] = 4.90\n",
    "d"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "del d['Burger']\n",
    "d"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## If-Anweisungen"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "if 2>1 or 1>2:\n",
    "    print ('Bedingung erfüllt.')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "y = 10\n",
    "x = 5 if y > 10 else 4\n",
    "\n",
    "print(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Schleifen"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "x = 5\n",
    "while x > 0:\n",
    "    x -= 1\n",
    "x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "for x in ['a', 'b', 'c']:\n",
    "    print(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Funktionen"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def sum_upto(n):\n",
    "    return n*(n+1)/2\n",
    "\n",
    "sum_upto(4)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Zur besseren Übersicht (insbesondere bei vielen Parametern) können diese auch namentlich zugewiesen werden."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sum_upto(n=4)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Funktionen können *Default-Parameter* haben, d.h. Werte, die von der Funktion als Standardwert verwendet werden (wenn kein anderer Wert übergeben wird). Default-Parameter müssen am Ende der Funktion stehen und übergeben werden."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def fun_with_default(x=3):\n",
    "    print('Parameter is {}'.format(x))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fun_with_default()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fun_with_default(x=4)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Funktionen können wie Variablen referenziert werden (Pointer auf die Funktion) und zum Beispiel als Parameter übergeben werden."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def calc_and_print(calc_function, n):\n",
    "    calc_result = calc_function(n)\n",
    "    print(calc_result)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "calc_and_print(sum_upto, 4)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Lambda-Funktionen\n",
    "I.d.R. für Inline-Funktionen. Können zum Beispiel an Funktionen als Parameter übergeben oder als Variable deklariert werden. Lambdas enthalten ein einzelnes Statement, dessen Wert automatisch der Rückgabewert ist."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "calc_square = lambda x: x**2\n",
    "calc_square(3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "calc_and_print(calc_square, 4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "calc_and_print(lambda x: x**3, 4)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## List Comprehensions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "y = [x**2 for x in range(10)]\n",
    "y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "xy = [(x, x**2) for x in range(10) if x%2 == 0]\n",
    "xy"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Klassen\n",
    "Objekte einer Klasse bekommen bei Methodenaufrufen als ersten Parameter automatisch das *\"self\"*-Objekt übergeben (vgl. *this* in Java). Dieser Parameter muss also immer auch als erster Parameter einer Klassenmethode übergeben werden. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Vehicle():\n",
    "    # Constructor\n",
    "    def __init__(self, n_wheels=4, noise='beep'):\n",
    "        self.n_wheels = n_wheels\n",
    "        self.noise = noise\n",
    "    \n",
    "    def make_noise(self):\n",
    "        print(self.noise)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "basicVehicle = Vehicle()\n",
    "basicVehicle.make_noise()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Properties sind immer von außen sichtbar und lassen sich verändern. Properties, die nicht zur Veränderung gedacht sind, werden nach Konvention durch zwei Unterstriche im Namen gekennzeichnet."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "basicVehicle.n_wheels"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Vererbung ist in Python möglich. In der Regel wird aber Duck-Typing verwendet. \n",
    "\n",
    "“When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck.”"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "bike = Vehicle(n_wheels=2, noise='ring')\n",
    "bike.make_noise()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Bike(Vehicle):\n",
    "    def __init__(self):\n",
    "        self.n_wheels = 2\n",
    "        self.noise = 'ring'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "Bike().make_noise()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Jupyter Notebook Grundlagen\n",
    "- Notebook besteht aus Zellen\n",
    "- Unter der Zelle wird der Rückgabewert des letzten Statements ausgegeben\n",
    "- Quellcode kann auf mehrere Zellen aufgeteilt werden (Variablen behalten ihre Gültigkeit/Sichtbarkeit)\n",
    "- Variablen sind auch nach dem Löschen von Zellen weiter sichtbar. Um den Speicher zu bereinigen *Kernel -> Restart*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Shortcuts\n",
    "Übersicht: *Help -> Keyboard Shortcuts*\n",
    "- *Enter*: Editiermodus für selektierte Zelle (grün)\n",
    "- *Esc*: Editiermodus verlassen/Kommandomodus (blau)\n",
    "- *Shift+Strg*: Selektierte Zelle ausführen\n",
    "- *Shift+Enter*: Selektierte Zelle ausführen und in nächste Zelle springen\n",
    "\n",
    "Im Editiermodus:\n",
    "- Tab: Autocomplete oder Einrücken\n",
    "\n",
    "Im Kommandomodus:\n",
    "- *B*: Zelle darunter einfügen\n",
    "- *A*: Zelle darüber einfügen\n",
    "- *DD*: Zelle löschen\n",
    "- *M*: Zelltyp Markdown (für formatierte beschreibende Texte)\n",
    "- *Y*: Zelltyp Code (Default)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "language_info": {
   "name": "python",
   "pygments_lexer": "ipython3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}