Du kannst for-Schlaufen auch verwenden um Listen zu definieren. Python hat dafür eine praktische Syntax, die zu beginn etwas rückwärts aussieht.
start_values = [[1,2,3,4],[7,6,5],[9,8,0]] maximas = [max(l) for l in start_values] print(maximas)
Diese Schreibweise ist auch praktisch wenn du mit range() Listen erstellen möchtest
l = [v**2 for v in range(10)]
Bisher haben wir mit Listen, Arrays und Strings drei Elemente iterierbare Typen kennengelernt. Ein weiterer praktischer Datentyp von Python sind Dictionaries. Dictionaries funktionieren ähnlich wie Listen. Die Einträge werden aber nicht einfach nummeriert. Stattdessen kannst du für jeden Eintrag einen Schlüssel festlegen.
ich = { 'name' : 'Nicola', 'start' : 2003 } print(ich['name']) print(ich['start'])
Auch ein Dict-Objekt hat verschiedene Methoden.
Besonders die beiden Methoden keys()
und values()
wirst du wohl häufig gebrauchen.
fakultaet = { 1 : 1, 2: 2, 3: 6, 4: 24, 5: 120 } sum = 0 for f in fakultaet.values(): sum += f print(sum)
Rekursive Funktionen sind Funktion, die sich selbst wieder aufrufen. Sie beziehen sich also auf sich selbst.
def rekurs(tiefe): print(tiefe) if tiefe > 0: rekurs(tiefe-1) rekurs(10)
Das Beispiel oben hätten wir auch mit einer einfachen Schlaufe erledigen können. Rekursive Funktionen sind vor allem dann nützlich, wenn sie für mehrere Unterargumente aufgerufen werden. Das Folgende Beispiel halbiert eine Strecke immer wieder, bis die gewünschte Tiefe erreicht ist.
from pylab import * def halbieren(min_val, max_val, tiefe): mitte = (max_val-min_val)/2. + min_val plot([mitte], [tiefe], 'b+') if tiefe > 0: halbieren(min_val, mitte, tiefe-1) halbieren(mitte, max_val, tiefe-1) min_val = 0 max_val = 16 tiefe = 3 plot([min_val, max_val], [tiefe,tiefe], 'r') halbieren(0, 16, tiefe) axis([min_val-1, max_val+1, -1, tiefe+1]) show()
Rekursive Funktionen können hier eine sehr elegante Lösung bieten. Ihr grösster Nachteil ist, dass rasch sehr viele Funktionsaufrufe verursachen. Das kann zu sehr langsamen Programmen führen.
Mit Zufallszahlen kannst du viele unterhaltsame Programm schreiben und auch für ernstere Aufgaben sind Zufallszahlen oft wichtig. Sowohl Standard-Python, wie auch NumPy bieten ein random-Modul.
Hinweis: Du darfst die Datei für dieses Beispiel nicht random.py
nennen.
Sonst nimmt Python beim import-Befehl deine Datei statt das random-Modul.
# Standard-Python import random wurf = 0 while wurf != 6: wurf = random.randint(1,6) print(wurf) gauss = [random.gauss(2, 0.5) for _ in range(20)] print(gauss) # und das gleiche mit pylab from pylab import * wurf = 0 while wurf != 6: wurf = randint(1,7) print(wurf) gauss = normal(2, 0.5, 20) print(gauss)
Wie gewohnt hilft dir die interne Hilfe von Python weiter, falls du mehr über die random-Module wissen möchtest.
Oft ist ein Beispiel die beste Art von Dokumentation. Doch das stimmt nur, wenn das Beispiel auch wirklich funktioniert. Python kann Beispiele in der Dokumentation automatisch testen. Damit das klappt, musst du dich aber an die Konvention halten. Glücklicherweise ist die Konvention sehr natürlich.
def calc_sum(a,b): """calculates the sum of two values takes two numbers and returns the sum of them Parameters ---------- a : any number first summand b : any number second summand Returns ------- a+b : same type as input the summ of the input Examples -------- >>> calc_sum(21,21) 42 >>> calc_sum(44.4,-2.4) 42.0 >>> calc_sum(2j,3) (3+2j) """ return a+b
Kopiere diese komplexe Funktion in eine Datei doctest-example.py.
Tipp: Mit [ctrl]+[u]
kannst du dir den HTML-Source anzeigen lassen.
Wenn du von dort kopierst, bleiben auch die Zeilenumbrüche erhalten.
In der Shell kannst du doctest dann mit folgendem Befehl starten.
python3 -m doctest -v doctest-example.py
Mit -m doctest
teilst du Python mit, dass
doctest ausgeführt werden soll.
-v
lässt doctest mehr Output ausgeben, so dass du siehst
was passiert.
Ohne -v würde doctest nur etwas ausgeben, falls ein Beispiel nicht
funktioniert.
Passe eines der Beispiel so an, dass es nicht mehr stimmt und
schaue was passiert.
Im folgenden findest du verschiedene, komplexere Aufgaben. Du musst jetzt nicht jede Aufgabe lösen. Wähle die spannendste(n) Aufgaben und bearbeite diese. Du kannst auch später noch hierher zurückkehren.
Überlege dir bei jeder Aufgabe zuerst, was du genau machen musst. Spiele allfällige Algorithmen zuerst von Hand durch und achte dabei darauf, welche Schritte sich wiederholen. Skizziere anschliessend auf Papier eine Programmstruktur sowie allfällig nötige Funktionen. Diskutiere deine Ideen mit anderen. (Ihr dürft diese Aufgaben auch gerne zu zweit lösen. Bei der Gelegenheit könnt ihr gleich die Verwendung von git üben.)
Verwende eines der random-Module um ein Programm zu schreiben, das dir hilft dein Kopfrechnen zu trainieren. Das Programm soll Zufallszahlen zu einfachen Rechnungen kombinieren, die du dann lösen musst. Überlege dir dabei auch, wo Probleme entstehen können und wie du diese verhindern kannst.
Sobald du ein funktionierendes Grundprogramm hast, kannst du dieses auch mit eigenen Ideen erweitern.
Implementiere ein Programm für folgenden Algorithmus
Lass dein Programm dann für ein paar 1000 Schritte laufen.
Schreib ein Programm, das eine Zahl startwert
einliest und ihre Primfaktoren bestimmt.
Verwende dabei folgenden Algorithmus
test_faktor = 2
startwert
durch test_faktor
teilbar ist, gibst du ihn aus,
teilst startwert
durch test_faktor
und fährst mit dem Ergebnis weiter.startwert
nicht durch test_faktor
teilbar ist,
erhöhst du test_faktor
um 1.Definiere zwei Funktionen die jeweils die n-te Fibonacci Zahl berechnen. Mache das einmal mittels Rekursion und einmal mittels while- oder for-Schlaufe. Verwende dann %timeit um herauszufinden wie schnell die beiden Funktionen sind.
Einen analogen Vergleich kannst du auch mit verschiedenen Implementation für die Fakultät durchführen. Weshalb ist der Effekt bei der Fakultät kleiner? Was passiert wenn du die Fakultät mittels Listen oder Arrays berechnest?
In dieser Aufgabe soll ein Programm geschrieben werden, das Graphiken wie die oben gezeigten erzeugt. Dies kannst du rekursive lösen. Dazu übergibst du der rekursiven Funktion die Endpunkte einer Linie. Die Funktion zeichnet dann entweder diese Linie oder berechnet die Abschnitte deiner Figur und ruft sich selbst für jeden Abschnitt neu auf. So ersetzt du jeweils jedes Linienstück durch die Figur selbst.
Figuren, welche nach diesem Muster gebildet werden, nennt man Koch-Kurven. Sie sind nach dem schwedischen Mathematiker Helge von Koch benannt. Er beschäftigte sich um die Jahrhundertwende des 19. und 20. Jahrhunderts, mit solchen Figuren.
Schreibe ein Programm das die Iterationstiefe einliest und zu dieser eine Koch-Kurve auf den Bildschirm zeichnet. Da sich die Orientierung deiner Linie laufen ändert, lohnt es sich diese Aufgabe mit Vektorrechnung zu lösen. Definiere die dafür nötigen Funktionen in einem separaten Modul.
Speziell elegant ist es, wenn du in deinem Programm auch die Grundform ohne viel Aufwand anpassen kannst.
Mit axis('equal')
bzw. mit ax.set_aspect('equal'
kannst du dafür sorgen, dass beide Achsen die gleiche Skalierung verwenden.
Dann werden deine gleichseitigen Dreiecke auch wirklich als gleichseitige Dreiecke dargestellt.