Python
und die IPython
-Shell¶Python
IPython
Shell (Ein- und Ausgabemaske) für benutzerfreundliche(re) Ein- und Ausgabe;
") unterdrückt werden"Hallo Welt"
42
42;
Strg
+<return>
-Taste) oder Semikolon (";
") getrennt werden"Hallo Welt"; "Hallo Welt2"
"Hallo Welt3"
42
#
")# Dies ist ein Kommentar
Python
-Typ: int
1
Python
-Typ: float
.
")<m>e<exp>
entspricht ${\tt <\!\!m\!\!>} \cdot 10^{{\tt 1.
1.3
3.3e-4
Python
-Typ: complex
1j
Python
-Typ: bool
True
False
Python
-Typ: NoneType
Jupyter
versteckt None
bzw. den NoneType
als AusgabeNone
None
ist das Ergebnis, wenn es (eigentlich) kein Ergebnis gibt -- wie bei der print
-Funktion:
print(print("a"))
Python
-Typ: str
'Hallo'
"Welt"
"""
Mehr-
zeiliger
Text!
"""
list
[ 1, 2, "Peter", 15.7, 1. + 2.j, 2 ]
tuple
( 1, 2, "Peter" )
1, 2, "Peter"
5 + 4.6
5 - 2.7
5 * 4
2j * 4j
7 / 5
Zahlen werden immer als endliche Kommazahlen gespeichert. Stichwort Gleitkommaarithmetik, säter in der Vorlesung.
1 / 17
15 // 2 # Ganzzahlige Division
#int(15 / 2)
5 ** 2 # Potenz
25 ** (1/2) # Achtung: Ergebnis keine ganze Zahl!
15 % 2 # Modulo
In- und Dekrement-Operationen
a = 1;
a += 1;
a
a -= 3;
a
Nur Runde Klammern "(
" bzw. ")
"
2 * 3 + 1
2 * (3 + 1)
2 + 2 * 2 ** 2
True and True, True and False, False and True, False and False
True or True, True or False, False or True, False or False
not True, not False
True ^ True, True ^ False, False ^ True, False ^ False
1 == 2, not 1 == 2, 1 > 2, 1 < 2
"Hans" == "Hans", "Hans" == "hans", "Hans" == "Peter"
in
-Operator¶1 in [ 1, 2, 3 ], 1 in ( 0, 2, 4 )
numpy
' einbinden, um mehr Funktionalität zu erhalten¶import numpy as np; # Später genauer
np.sqrt(25)
np.pi
np.e
np.exp(2)
np.log(1)
np.abs(-5)
Eingabe:
[ ]: np.
<tab>
np.log10(1000)
Diese müssen nicht unbedingt einen Wert zurück liefern
type("Hallo?")
print("Hallo?") # Achtung: kein "Out"
np.linspace(0, 1, 5)
"{0}-{1}, etwa {2}".format("Gauß", "Algorithmus", 1810);
Formatierung angeben (Typ, Länge/Stellen) (Achtung: falsche Typangabe führt zu Fehlermeldung)
"|{0:6d}|, |{1:5.2f}%| |{2:>10s}|".format(1810, 1.2, "Hallo")
liste = [ 42, 17 ];
print(liste);
print(*liste);
Ist äquivalent zu
print(liste[0], liste[1]);
"{0} zu {1}".format(*liste)
help(np.linspace);
Besser in IPython
(beenden mit q
-Taste):
?np.linspace
np.linspace(0, 1, 5, retstep = True)
a = 1;
a
b = 1.; s = "Hallo Welt";
b, s
%whos
Das Modul np
erscheint auch als Variable
type(a)
Um das Ergebnis zu sehen print verwenden oder die Variable am Ende wiederholen
a = 1;
print(a);
print("a = {0}".format(a));
a
Achtung: das Folgende ist keine logisch falsche Aussage, sondern eine Zuweisung
a = a + 1;
print(a);
f = lambda x: 1 / (1 + x**2);
print(f(0), f(1), f(-1))
%whos
import numpy;
numpy.cos(1)
%whos
%reset -f
%whos
import numpy as np;
Der Zugriffoperator sind eckige Klammern "[
" und "]
".
Es wird von Null ab indiziert.
a = [ 1, 2, 3, 4, 5, 6, 7, 8 ]
b = 5, 6, 7, 8
a[0], b[2], a[3]
Dabei indiziert -1
das letzte Element, -2
das Vorletzte, usw..
a[-1], a[-2]
a[1:3] # Index 1 bis zu dem vor 3, d.h. 2.-3. Element
Slicing behält den Typ bei (d.h. list
s bleiben list
s, tuple
s bleiben tuple
s, etc.)
b[1:3]
Die Endindizes können weggelassen werden, wenn das erste bzw. letzte Argument gewählt werden soll
a[:2], a[0:2], a[2:], a[2:8]
In größeren Schritten
a[1:5:2]
a[::2]
b[::3]
Rückwärts
a[-1:-5:-1]
Erzeuge die Zahlen 5 (inklusive) bis 10 (exklusive) in Zweierschritten
a = range(5, 10, 2);
list(a)
Tuples sind unveränderbar
a[1] = 3
Listen sind veränderbar
a = list(a);
print(a);
a[1] = 3
print(a)
Achtung: Alle Variablen sind Referenzen:
b = a;
b[1] = 5;
print(a) # Auch hier geändert!
Ausweg: Kopieren
b = list(a);
b[1] = 7;
print(a, b)
join
und split
¶print(", ".join([ "a", "b", "c" ]))
"Hallo Welt ??".split(" ")
numpy
arrays
: Matrizen, Vektoren und Lineare Algebra¶import numpy as np;
import scipy.linalg as la;
# Ein 3x2-Array in python
a1 = [ 1, 2, 3 ];
b1 = [ 4, 5, 6 ];
c1 = [ a1, b1 ];
print(c1)
c = np.array(c1);
print(c);
c[1, 1]
d = np.array([c, c])
d
d[1, 1, 1]
np.array([ d, d ])
print(a.ndim, c.ndim, d.ndim) # Anzahl der "Dimensionen"
print(a.shape, c.shape, d.shape) # Anzahl der Elemente pro "Dimension"
print(a.size, c.size, d.size) # Anzahl der Elemente
a * b
a, b, c
a + b
Achtung: Dies kann eine Falle sein!
a + c
Diese Zeile ist zu verstehen als
np.array([a, a]) + c
Aber:
a + np.array([ 1, 2 ])
a - b, a / b
np.cos(a)
f = lambda x: 1 / (1 + x**2);
f(a)
a = np.array([ True, True, False, False ]);
b = np.array([ True, False, True, False ]);
Leider:
a or b
Ausweg:
np.logical_or(a, b)
c
c.T, c.conj()
#print(c.transpose())
print(c.diagonal())
print(c.real)
print(c.imag)
#print(np.tril(c))
#print(np.triu(c))
print(c.min())
print(c.max())
print(c.min(0))
print(c.min(1))
print(c.mean())
print(c.sum())
print(c.prod())
np.array([ 1, 2, 3 ]), np.array((1, 2, 3))
Oder direkt mit der numpy
Funktion arange
np.arange(3, 10, 2)
np.zeros(( 3, 2 ))
np.ones(( 4, 3 )) * 42
Verteile gleichmäßig Einträge
np.linspace(0, 1)
np.linspace(0, 1, 15)
Uminterpretation der Daten
a = np.arange(12) + 1;
a
a.reshape(12, 1)
a.reshape(1, 12)
a.reshape(3, 4)
a.reshape(3, 1, 4)
a.reshape(3, 2, 2)
a.reshape(3, -1) # Eine Dimension kann automatisch ergänzt werden, mit dem Rest, der Fehlt
Das Produkt der Längen muss der Anzahl der Elemente entsprechen!
Als Formel: np.prod(a.shape) == a.size
a.reshape(3, 2, 1)
Achtung: Auch hier wird nicht kopiert!
b = a.reshape(12, 1)
b[2] = -1; a, b
a = np.array([ 1, 2 ])
b = np.array([ 3, 4 ])
np.concatenate((a, b), 0)
np.concatenate((a, b), 1)
a = a.reshape(1, 2);
b = b.reshape(1, 2);
np.concatenate((a, b), 0)
np.concatenate((a, b), 1)
a = np.linspace(0, 3, 7);
a
Wie bei list
, tuple
, etc.
a[0], a[5], a[-5]
Slicing wie bei Listen
a[1::2]
Indexlisten, Wiederholung der Indizes sind möglich, Dopplungen und negative Indizes erlaubt
ind = [ 1, 2, 2, 5, -4 ];
a[ind]
ind = [ True, False, False, True, False, False, True ];
a[ind]
Bestimme alle ganzzahligen Einträge
ind = a == a.round();
ind, a[ind], a[a == a.round()]
Nötiger Vorspann
import matplotlib.pylab as plt;
# Nur für die Darstellung auf der Webseite, im Programm nicht nötig
%matplotlib inline
x = np.linspace(-1, 1);
f = lambda x: x ** 3;
g = lambda x: np.sin(np.pi * x);
h = lambda x: 1 / x;
plt.plot(x, f(x));
plt.plot(x, g(x));
plt.plot(x, h(x));
plt.plot(x, f(x), 'm');
plt.plot(x, f(x), 'm', x, g(x), 'r--', x, h(x) / 60, 'k:');
plt.plot(x, f(x), 'm', x, g(x), 'r--', x, h(x) / 60, 'k:');
# Beschriftungen (wichtig!)
plt.legend([ 'f(x)', 'g(x)', 'h(x)/60' ]);
plt.xlabel("x");
plt.ylabel("y");
x = np.linspace(1e-16, 1)
f = lambda x: x**2
plt.semilogx(x, f(x))
plt.semilogy(x, f(x))
plt.loglog(x, f(x))
A = np.arange(9).reshape((3, 3));
B = np.identity(3);
C = np.diag([1, 2, 3]);
print("A =\n", A, "\nB =\n", B, "\nC =\n", C)
Beachte, dass die array
-Einträge den Anfangstyp behalten!
A.dtype, B.dtype
Auch bei der Zuweisung!
A[0,0] = 5.5; B[0,0] = 5.5;
A[0,0], B[0,0] # Achtung, der A-Eintrag ist ganzzahlig!
D = la.circulant([1, 2, 3])
D
Z = np.diag([ 4, 4, 4 ]) + 0j;
Z
x = np.array((1, 2, 1)) + 0. # Ein 3-elementiges array (ohne 2. Dimension)
Können auch explizit $1 \times n$ oder n $\times$ 1 groß macht werden:
y = x.reshape(1, -1)
z = x.reshape(-1, 1)
y, z
In Python
ist die Matrix-Multiplikation (Matrix mal Matrix
, Matrix mal Vektor
, Vektor mal Vektor
, ...) mit dem @
-Operator realisiert:
A @ B, A @ x, x @ A
Achtung: Ein einfaches *
ist eine komponentenweise Operation (s.o.)
A * B
Ainv = la.solve(A, np.eye(3))
Ainv, Ainv @ A, A @ Ainv # Identität bis auf Rundungsfehler
Blöcke fassen mehrere Befehle auf einer Ebene zusammen. Befehle eines Blockes werden gemeinsam hintereinander ausgeführt. Es gibt Ausnahmen, die ein vorzeitiges Beenden der Ausführung eines zusammenhängenden Blockes hervorrufen.
:
") festgelegtBasisebene
block:
erste Ebene
innerer block:
zweite Ebene
weiterer Befehl
wieder auf der ersten Ebene
nächster Block:
neue 2. Ebene
weiter ...
Basisebene
Teste eine Bedingung (Wahrheitswert) und springe in Abhängingkeit des Wertes.
Format:
if <Wahrheitswert1>:
# Code, der ausgeführt wird, wenn <Wahrheitswert1> True ist
elif <Wahrheitswert2>:
# Code, der ausgeführt wird, wenn <Wahrheitswert1> False
# und <Wahrheitswert2> True ist
elif ....:
# usw.
else:
# Code, der ausgeführt wird, wenn alle Wahrheitswerte vorher
# False waren.
a, b = np.random.randint(0, 5, 2);
print("a: {0}, b: {1}, Maximum:".format(a, b));
if a > b:
print("a");
elif a < b:
print("b");
else:
print("Beide gleich.");
Python
kennt kein switch
/case
for
-Schleife¶Im Vorhineinvorher festgelegte Iteration. Es wird über eine Indexliste Iteriert, der aktuelle Index kann über eine Variable zugegriffen werden.
Format:
for <index> in <indexliste>:
# Code, der für jeden <index> in <indexliste> ausgeführt
# wird.
# Der Wert der Variable <index> hat den entsprechenden Wert.
for kk in range(10):
print(kk);
typen = [ "zu Fuß", "Fahrrad", "Auto", "Zug" ];
for typ in typen:
print(typ);
Iteration über Paare
liste = list(zip(typen, [ 4, 25, 50, 100 ]));
liste
for typ, geschwindigkeit in liste:
print("{0:10s}: {1:3d} km/h".format(typ, geschwindigkeit))
Elemente in einer Liste aufzählen:
for index, typ in enumerate(typen):
print("Typ {0}: {1}".format(index, typ));
while
-Schleife¶Schleife mit immer wieder neu getestetem Abbruch.
Format:
while <Wahrheitswert>:
# Code, der so lange ausgeführt wird, wie Wahrheitswert True
# ist.
Spiel: Wir würfeln so lange mit einem sechs-seitigen Würfel, bis die Summe der Würfe 21 übersteigt.
summe = 0;
runde = 0;
while summe <= 21:
wurf = np.random.randint(1, 7);
runde += 1;
summe += wurf;
print("Wurf {0}: {1}, Summe: {2:2d}".format(runde, wurf, summe));
print("Fertig nach {0} Würfen.".format(runde));
Bei Schleifen können Durchläufe vorzeitig beendet werden oder die ganze Schleife vorzeitig beendet werden.
continue
beendet den aktuellen Durchlauf und startet die Schleife
von vorn.for
-Schleifen, wird der nächste Index verwendet, falls
vorhanden.
Anderenfalls wird die Schleife beendent.while
-Schleifen wird die Bedingung neu geprüft.break
beendet die gesamte Iteration.Spiel:
punkte = np.array([ 0, 0 ])
for runde in range(1, 8):
wuerfe = np.random.randint(1, 7, 2);
print("Runde {0:2d}: Sp. 1 würfelt {1}, Sp. 2 würfelt eine {2}.".format(
runde, *wuerfe));
if wuerfe.min() < 3:
print("Runde ungültig.");
continue;
punkte += wuerfe;
print("Punktestand: {0} zu {1}".format(punkte[0], punkte[1]));
if punkte.max() > 21:
break;
print("Endstand nach {0} Runden: {1} zu {2}".format(runde, punkte[0], punkte[1]))
Eine weitere Möglichkeit, Programme oder Schleifen vorzeitig zu beenden, sind Fehlermeldungen. Diese dürfen an einer beliebtigen Stelle des Programms stehen.
print("Hallo 1");
raise(Exception("Dies ist eine Fehlermeldung"));
print("Hallo 2");
wurf = np.random.randint(1, 7);
if wurf % 2 == 0:
raise(Exception("Gerade würfe werden nicht akzeptiert ({0})".format(wurf)))
wurf
Assertations schließen eine Fallunterscheidung mit ein.
Der Fehler wird ausgelöst, wenn die Bedingung False
ist.
wurf = np.random.randint(1, 7);
assert wurf % 2 == 1, "Gerade würfe werden nicht akzeptiert ({0})".format(wurf)
wurf
Funktionen fassen einen eine Reihe von Anweisungen zusammen, die über einen bestimmten Namen aufgerufen werden können.
Funktionen geben immer einen Wert zurück, der falls nicht explizit angegeben None
ist.
Wir kennen bereits eine Form einfacher eigener Funktionen:
solche, die mit lambda
definiert werden.
myPower = lambda x, a: x ** a;
myPower(2, 10)
Kompliziertere Funktionen, etwa solche die sich nicht, oder nicht einfach in einem einzelnen Befehl ausdrücken lassen, können mit def
erzeugt werden.
Format:
def <funktionsname>(<arg1>, <arg2>, ...):
# Code der durch den Aufruf von <funktionsname>(...)
# ausgeführt wird.
# Gegebenenfalls:
return <wert>;
def myPower(x, a):
print("Meine eigene Potenzfunktion wird ausgeführt.");
return x**a;
myPower(2, 10)
Eine Hilfe (Dokumentation) zur Funktion kann als Zeichenkette als erste Zeile des Funktionskörpers definiert werden.
def myCommentedFunction(text):
"""
Dies ist der Hilfetext zu `myCommentedFunction`.
Blah.
"""
print(text)
help(myCommentedFunction)
?myCommentedFunction
def myPower(x, a = 2): # Wenn nicht angegeben, ist a = 2
return x**a;
myPower(2), myPower(2, 2), myPower(2, 3)
def myPower(x = 2, a = 2): # Wenn nicht angegeben, sind x = 2 und a = 2
return x**a;
myPower(), myPower(3), myPower(3, 3)
# Nur das zweite Argument angeben (dann explizit mit Namen)
myPower(a = 3)
Funktionen haben ihren eigenen Namensraum, können (nur lesend) auf den sie umgebenden Namensraum zugreifen.
a = 15;
def fun():
print(a);
x = 16;
fun()
print(x)
Wenn eine Variable in einer Funktion zugewiesen wird, die auch außerhalb existiert, wird innerhalb der Funktion eine zweite Version der Variable erstellt.
a = 15;
def fun():
a = 16;
fun();
print(a)
Die Funktion locals()
gibt einem ein dict
aller lokal in einer Funktion definierten Variablen.
Die Variablennamen sind die Schlüssel, deren Werte die Werte des dict
s.
def fun():
print(locals());
a = 15;
print(locals());
fun();