diff --git a/notebooks/recap.ipynb b/notebooks/recap.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..f215a73c424120267f317c764276037cf082c8ba
--- /dev/null
+++ b/notebooks/recap.ipynb
@@ -0,0 +1,751 @@
+{
+ "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
+}