Programmiersprache Python

Vorteile

Nachteile

Python-Installation

Essentielles, auf Institutsrechnern bereits verfügbar:

Empfehlenswert:

Direkt lauffähige, recht vollständige Distribution mit aktuellen Programmversionen (Linux ohne Root, Windows, OSX):

Dokumentation zum Einstieg:

Python-Grundlagen

Hello World

helloworld.py:

#!/usr/bin/env python
print "Hello World"

Ausführung:

max@max-ThinkPad-X220:~/lehre/2013-python-tutorial$ python helloworld.py 
Hello World

Interaktiver Interpreter (python oder ipython):

max@max-ThinkPad-X220:~/lehre/2013-python-tutorial$ python
Python 2.7.3 (default, Aug  1 2012, 05:14:39) 
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> print "Hello World"
Hello World
>>>

In diesem Notebook eingebetteter Interpreter:

In [85]:
print "Hello World"
Hello World

Variablen und numerische Datentypen

In [86]:
x = 1       # int
y = 0.73    # float
z = 'Hallo' # string
In [87]:
a = x + y # float
print a
1.73
In [88]:
x = z     # x jetzt string
a = x + y # Fehler
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-88-e4b3c3445b1d> in <module>()
      1 x = z     # x jetzt string
----> 2 a = x + y # Fehler

TypeError: cannot concatenate 'str' and 'float' objects

Verschiedene Integer-Typen

In [89]:
print 25**2                     # int
625
In [90]:
print 25**200                   # arbitrary precision
3872591914849318272818030633286351847570219192048790865487762941344416348097685964862682234277014596908057542507554467539370836398992350315522318050653350492002436065270530802738432038373174754090809367646454942400181270162578968846816261130394654088604511343874037265777587890625

Floating point

In [91]:
2.6+7.8
Out[91]:
10.4
In [92]:
2.5**2
Out[92]:
6.25
In [93]:
2.5**(1./10)
Out[93]:
1.0959582263852172

Warnung: Integer- vs. Float-Division -- Fehlerquelle

In [94]:
f = 2/3
f
Out[94]:
0.6666666666666666
In [95]:
f = (2/3) * 1.5
f
Out[95]:
1.0
In [96]:
f = float(2) / 3
f
Out[96]:
0.6666666666666666

Ab Python 3.0 liefert / immer Fließkommawerte, für Integerdivision gibt es den neuen Operator //. Wir behelfen uns bei Python 2.x auf folgende Art:

In [97]:
from __future__ import division 
In [98]:
2/3
Out[98]:
0.6666666666666666
In [99]:
2//3
Out[99]:
0

Mathematische Funktionen und Konstanten liegen im Modul math

In [100]:
import math
math.sin(math.pi / 2)
Out[100]:
1.0

Nützlich im interaktiven Interpreter:

In [101]:
dir(math)                       # Variablen, Funktionen etc. definiert
                                # im Modul
Out[101]:
['__doc__',
 '__name__',
 '__package__',
 'acos',
 'acosh',
 'asin',
 'asinh',
 'atan',
 'atan2',
 'atanh',
 'ceil',
 'copysign',
 'cos',
 'cosh',
 'degrees',
 'e',
 'erf',
 'erfc',
 'exp',
 'expm1',
 'fabs',
 'factorial',
 'floor',
 'fmod',
 'frexp',
 'fsum',
 'gamma',
 'hypot',
 'isinf',
 'isnan',
 'ldexp',
 'lgamma',
 'log',
 'log10',
 'log1p',
 'modf',
 'pi',
 'pow',
 'radians',
 'sin',
 'sinh',
 'sqrt',
 'tan',
 'tanh',
 'trunc']
In [102]:
help(math.sin)                  # Dokumentation anzeigen
Help on built-in function sin in module math:

sin(...)
    sin(x)
    
    Return the sine of x (measured in radians).

Komplexe Zahlen

In [103]:
import cmath
cmath.sqrt(-1)
Out[103]:
1j
In [104]:
cmath.exp(1j * cmath.pi / 3)
Out[104]:
(0.5000000000000001+0.8660254037844386j)

Zeichenketten

In [105]:
a = 'Hello '                  # Single quotes
b = "World "                  # Double quotes
c = "Bob said 'hey there.'"  # A mix of both 
d = "\'"
print d
e = b + a  # concatenate
print e
'
World Hello 
In [106]:
f = a*3
print f
Hello Hello Hello 

Elementzugriff (Indizierung beginnt bei 0), Slicing [erstes Element:Position hinter letztem Element]

In [107]:
c[5]       # (5+1). Element von c
Out[107]:
'a'
In [108]:
c[2:8]     # (3.-8.). Element von c
Out[108]:
'b said'
In [109]:
c[:3]
Out[109]:
'Bob'
In [110]:
c[-12:]          # negative Zahlen zählen vom Ende zurück
Out[110]:
"'hey there.'"
In [111]:
c[:]
Out[111]:
"Bob said 'hey there.'"

String-Methoden: Funktionen, die auf einem Zeichenkettenobjekt operieren.

In [112]:
c.count('e')
Out[112]:
3
In [113]:
c.upper()
Out[113]:
"BOB SAID 'HEY THERE.'"
In [114]:
"abracadabra".find("ra")
Out[114]:
2
In [115]:
"abracadabra".replace("ra", "lu")
Out[115]:
'ablucadablu'
In [116]:
c[3] = 'a'
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-116-c439af4de3ce> in <module>()
----> 1 c[3] = 'a'

TypeError: 'str' object does not support item assignment

Strings sind unveränderliche Objekte, ggf. werden neue Strings von den Methoden zurück geliefert.

In [117]:
e="abracadabra"
print e.replace("ra", "lu") 
print e
ablucadablu
abracadabra

Listen

Zusammenfassung beliebiger Objekte

In [118]:
L = [ 1, 5, 9, 45, 3, 72, 27 ]
len(L)
Out[118]:
7

Elementzugriff wie bei Zeichenketten

In [119]:
L[6]
Out[119]:
27
In [120]:
L[8]
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-120-957688e9c48d> in <module>()
----> 1 L[8]

IndexError: list index out of range

Listen können verändert werden

In [121]:
L[2] = 11
L
Out[121]:
[1, 5, 11, 45, 3, 72, 27]
In [122]:
L.sort()
L
Out[122]:
[1, 3, 5, 11, 27, 45, 72]
In [123]:
L.append(87)
L
Out[123]:
[1, 3, 5, 11, 27, 45, 72, 87]
In [124]:
L.insert(2, 33)                  # an Position 2 einfügen
L
Out[124]:
[1, 3, 33, 5, 11, 27, 45, 72, 87]
In [125]:
del L[3:5] # Loesche Element 4-5
L
Out[125]:
[1, 3, 33, 27, 45, 72, 87]
In [126]:
K=[0]*10 # List mit 10 Elementen, alle 0
K
Out[126]:
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
In [127]:
M = [1, 2.45, (1+4j), L[1:5]]  # mixed list
M
Out[127]:
[1, 2.45, (1+4j), [3, 33, 27, 45]]
In [128]:
M[3][2]
Out[128]:
27

Mit range() Listen aus Zahlenbereichen erzeugen

In [129]:
G = range(20)
G
Out[129]:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
In [130]:
G = range(1, 11)
G
Out[130]:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
In [131]:
G = range(1, 11, 2)
G
Out[131]:
[1, 3, 5, 7, 9]
In [132]:
import numpy as np
np.arange(1, 10, 0.2)
Out[132]:
array([ 1. ,  1.2,  1.4,  1.6,  1.8,  2. ,  2.2,  2.4,  2.6,  2.8,  3. ,
        3.2,  3.4,  3.6,  3.8,  4. ,  4.2,  4.4,  4.6,  4.8,  5. ,  5.2,
        5.4,  5.6,  5.8,  6. ,  6.2,  6.4,  6.6,  6.8,  7. ,  7.2,  7.4,
        7.6,  7.8,  8. ,  8.2,  8.4,  8.6,  8.8,  9. ,  9.2,  9.4,  9.6,
        9.8])

Slicing

In [133]:
a = range(10)
a
Out[133]:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [134]:
a[4:7]
Out[134]:
[4, 5, 6]
In [135]:
a[-3:]
Out[135]:
[7, 8, 9]
In [136]:
a[-3:-1]
Out[136]:
[7, 8]
In [137]:
a[-3:2]
Out[137]:
[]

Dictionaries

"assoziatives Array", "map": Verknüpfung von (Schlüssel, Wert)-Paaren

In [138]:
D = {'food':'Spam', 'quantity':4, 'color':'pink'}
D['food']
Out[138]:
'Spam'
In [139]:
D['size']                       # nichtgesetzter Schlüssel
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-139-7209e65be077> in <module>()
----> 1 D['size']                       # nichtgesetzter Schlüssel

KeyError: 'size'

Dictionaries sind veränderlich wie Listen

In [140]:
D['quantity'] = 6
D['size'] = 20            #neuer Schlüssel
In [141]:
D
Out[141]:
{'color': 'pink', 'food': 'Spam', 'quantity': 6, 'size': 20}

Vergleiche und Schleifen

Boolsche Werte

In [142]:
1 < 4
Out[142]:
True
In [143]:
5 < 4
Out[143]:
False
In [144]:
0.3 == 0.1 + 0.2
Out[144]:
False

Logische Ebenen im Code werden nur durch : und Einrückung ausgedrückt -- keine Klammern oder begin-end-Blöcke

Bedingungen mit if

In [145]:
a = 1
b = 2
c = 3

if a < b:
   if c > b:
     print 1
     print a, b, c
   else:
      print 2
else:
   print 3   
1
1 2 3
In [146]:
x = 'spam'
while x:        # wiederhole, solange Bedingung "wahr", d.h. x != ''
   print x,
   x = x[:-1]                   # letztes Zeichen entfernen   
spam spa sp s

for-Schleife: iteriere über alle Elemente einer Liste:

In [147]:
for x in ['spam', 'eggs', 'ham']:
    print x,
spam eggs ham

Für "klassiche" for-Schleifen: Kombination mit range()

In [148]:
for i in range(0, 10, 2):
    print i,
0 2 4 6 8

List Comprehensions

Aufgabe: Finde alle Quadrate der natürlichen Zahlen bis 10

C-artiger Code:

In [149]:
l = []
for i in range(1, 11):
    l.append(i**2)
print l
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

"Pythonischer" Code:

In [150]:
l = [ i**2 for i in xrange(1,11) ]
print l
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

Auch kompliziertere Ausdrücke möglich:

In [151]:
l1 = []
for i in range(1,7):
    for word in ['sausages', 'spam', 'eggs', 'ham']:
        if i <= len(word):
           l1.append(word*i)
print l1
print
l2 = [word*i for i in range(1,7) for word in ['sausages', 'spam', 'eggs', 'ham'] if i <= len(word)]
print l1 == l2
['sausages', 'spam', 'eggs', 'ham', 'sausagessausages', 'spamspam', 'eggseggs', 'hamham', 'sausagessausagessausages', 'spamspamspam', 'eggseggseggs', 'hamhamham', 'sausagessausagessausagessausages', 'spamspamspamspam', 'eggseggseggseggs', 'sausagessausagessausagessausagessausages', 'sausagessausagessausagessausagessausagessausages']

True

Funktionen, Tupel

In [152]:
def square(argument):
    return argument*argument
In [153]:
square(3)
Out[153]:
9

Funktionen sind Objekte, wie Variablen zu verwenden

In [154]:
def applyToList(f, l):
    return [f(x) for x in l]

applyToList(square, range(11))
Out[154]:
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

Achtung: Funktionsargumente werden als Referenz übergeben, nicht als kopierter Wert

In [155]:
def dreiGroesste(l):
    l.sort()
    return l[-3:]
l = [17, 2, 81, 30, -45]
In [156]:
print l
print dreiGroesste(l)
print l                         # Liste hat sich verändert
[17, 2, 81, 30, -45]
[17, 30, 81]
[-45, 2, 17, 30, 81]

Abhilfe: Explizit kopieren

In [157]:
def dreiGroesste1(liste):
    l = liste[:]                # kopiere alle Eintraege (Slice-Notation)
    l.sort()
    return l[-3:]
l = [17, 2, 81, 30, -45]
print dreiGroesste1(l)
print l

print sorted(l[-3:])
[17, 30, 81]
[17, 2, 81, 30, -45]
[-45, 30, 81]
In [158]:
def dreiGroesste2(liste):
    from copy import copy    # eine Funktion aus einem Modul importieren ("shallow copy")
    l = copy(liste)
    l.sort()
    return l[-3:]
l = [17, 2, 81, 30, -45]
print dreiGroesste1(l)
print l
[17, 30, 81]
[17, 2, 81, 30, -45]

Tupel sind ähnlich zu Listen, können nach dem Erzeugen aber nicht verändert werden

In [159]:
tup = (1, 2, 3)                 # Klammern optional
tup[2]
Out[159]:
3
In [160]:
tup[2] = 5
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-160-4c74e110ff20> in <module>()
----> 1 tup[2] = 5

TypeError: 'tuple' object does not support item assignment

Tupel werden gerne verwendet, um mehrere Werte von einer Funktion zurückzugeben

In [161]:
def squareAndCube(x):
    return [x**2, x**3]
s, c = squareAndCube(5)
print s
s += 2
print s
print c
25
27
125
In [162]:
import copy
l1 = [ [1, 2, 3], [4, 5, 6] ]
l2 = copy.copy(l1)
print l1
print l2
l2[0] = "zonk"
print l1
print l2
l2 = copy.deepcopy(l1)
l2[0][0] = "zonk"
print l1
print l2
[[1, 2, 3], [4, 5, 6]]
[[1, 2, 3], [4, 5, 6]]
[[1, 2, 3], [4, 5, 6]]
['zonk', [4, 5, 6]]
[[1, 2, 3], [4, 5, 6]]
[['zonk', 2, 3], [4, 5, 6]]
In [163]:
help(copy)
Help on module copy:

NAME
    copy - Generic (shallow and deep) copying operations.

FILE
    /usr/lib/python2.7/copy.py

MODULE DOCS
    https://docs.python.org/library/copy

DESCRIPTION
    Interface summary:
    
            import copy
    
            x = copy.copy(y)        # make a shallow copy of y
            x = copy.deepcopy(y)    # make a deep copy of y
    
    For module specific errors, copy.Error is raised.
    
    The difference between shallow and deep copying is only relevant for
    compound objects (objects that contain other objects, like lists or
    class instances).
    
    - A shallow copy constructs a new compound object and then (to the
      extent possible) inserts *the same objects* into it that the
      original contains.
    
    - A deep copy constructs a new compound object and then, recursively,
      inserts *copies* into it of the objects found in the original.
    
    Two problems often exist with deep copy operations that don't exist
    with shallow copy operations:
    
     a) recursive objects (compound objects that, directly or indirectly,
        contain a reference to themselves) may cause a recursive loop
    
     b) because deep copy copies *everything* it may copy too much, e.g.
        administrative data structures that should be shared even between
        copies
    
    Python's deep copy operation avoids these problems by:
    
     a) keeping a table of objects already copied during the current
        copying pass
    
     b) letting user-defined classes override the copying operation or the
        set of components copied
    
    This version does not copy types like module, class, function, method,
    nor stack trace, stack frame, nor file, socket, window, nor array, nor
    any similar types.
    
    Classes can use the same interfaces to control copying that they use
    to control pickling: they can define methods called __getinitargs__(),
    __getstate__() and __setstate__().  See the documentation for module
    "pickle" for information on these methods.

CLASSES
    exceptions.Exception(exceptions.BaseException)
        Error
    
    class Error(exceptions.Exception)
     |  Method resolution order:
     |      Error
     |      exceptions.Exception
     |      exceptions.BaseException
     |      __builtin__.object
     |  
     |  Data descriptors defined here:
     |  
     |  __weakref__
     |      list of weak references to the object (if defined)
     |  
     |  ----------------------------------------------------------------------
     |  Methods inherited from exceptions.Exception:
     |  
     |  __init__(...)
     |      x.__init__(...) initializes x; see help(type(x)) for signature
     |  
     |  ----------------------------------------------------------------------
     |  Data and other attributes inherited from exceptions.Exception:
     |  
     |  __new__ = <built-in method __new__ of type object>
     |      T.__new__(S, ...) -> a new object with type S, a subtype of T
     |  
     |  ----------------------------------------------------------------------
     |  Methods inherited from exceptions.BaseException:
     |  
     |  __delattr__(...)
     |      x.__delattr__('name') <==> del x.name
     |  
     |  __getattribute__(...)
     |      x.__getattribute__('name') <==> x.name
     |  
     |  __getitem__(...)
     |      x.__getitem__(y) <==> x[y]
     |  
     |  __getslice__(...)
     |      x.__getslice__(i, j) <==> x[i:j]
     |      
     |      Use of negative indices is not supported.
     |  
     |  __reduce__(...)
     |  
     |  __repr__(...)
     |      x.__repr__() <==> repr(x)
     |  
     |  __setattr__(...)
     |      x.__setattr__('name', value) <==> x.name = value
     |  
     |  __setstate__(...)
     |  
     |  __str__(...)
     |      x.__str__() <==> str(x)
     |  
     |  __unicode__(...)
     |  
     |  ----------------------------------------------------------------------
     |  Data descriptors inherited from exceptions.BaseException:
     |  
     |  __dict__
     |  
     |  args
     |  
     |  message

FUNCTIONS
    copy(x)
        Shallow copy operation on arbitrary Python objects.
        
        See the module's __doc__ string for more info.
    
    deepcopy(x, memo=None, _nil=[])
        Deep copy operation on arbitrary Python objects.
        
        See the module's __doc__ string for more info.

DATA
    __all__ = ['Error', 'copy', 'deepcopy']


Numpy: $d$-dimensionale Arrays

C-schnelle Routinen für große Felder

In [164]:
import numpy as np
a = np.arange(15)               # range() für Arrays
a = a.reshape(3,5)              # 3 Zeilen, 5 Spalten
a
Out[164]:
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14]])
In [165]:
print a.shape
print a.ndim
print a.size
(3, 5)
2
15

Arrays aus beliebigem iterierbaren Objekt erzeugen, Datentyp explizit festlegen

In [166]:
a = np.array([x**2 for x in range(10)], dtype='float')
a
Out[166]:
array([  0.,   1.,   4.,   9.,  16.,  25.,  36.,  49.,  64.,  81.])
In [167]:
a = np.array( [ [x*y for x in range(5)] for y in range(4)] )
a
Out[167]:
array([[ 0,  0,  0,  0,  0],
       [ 0,  1,  2,  3,  4],
       [ 0,  2,  4,  6,  8],
       [ 0,  3,  6,  9, 12]])

Rechenoperationen auf Arrays:

In [168]:
x = np.linspace(0, 2*np.pi, 20)
x
Out[168]:
array([ 0.        ,  0.33069396,  0.66138793,  0.99208189,  1.32277585,
        1.65346982,  1.98416378,  2.31485774,  2.64555171,  2.97624567,
        3.30693964,  3.6376336 ,  3.96832756,  4.29902153,  4.62971549,
        4.96040945,  5.29110342,  5.62179738,  5.95249134,  6.28318531])
In [169]:
y = np.cos(x)
y
Out[169]:
array([ 1.        ,  0.94581724,  0.78914051,  0.54694816,  0.24548549,
       -0.08257935, -0.40169542, -0.67728157, -0.87947375, -0.9863613 ,
       -0.9863613 , -0.87947375, -0.67728157, -0.40169542, -0.08257935,
        0.24548549,  0.54694816,  0.78914051,  0.94581724,  1.        ])
In [170]:
2 * np.linspace(0, 2*np.pi, 20) + y
Out[170]:
array([  1.        ,   1.60720517,   2.11191636,   2.53111194,
         2.8910372 ,   3.22436029,   3.56663214,   3.95243392,
         4.41162967,   4.96613004,   5.62751797,   6.39579345,
         7.25937355,   8.19634763,   9.17685163,  10.16630439,
        11.12915499,  12.03273527,  12.85079993,  13.56637061])

Vektor-/Matrizenrechnung, Zufallszahlen

In [171]:
A = np.random.random(20).reshape(5,4)
A
Out[171]:
array([[ 0.48338662,  0.03486614,  0.35250375,  0.48956011],
       [ 0.14395604,  0.35601808,  0.70903865,  0.9131345 ],
       [ 0.75429594,  0.33171673,  0.99989876,  0.96116405],
       [ 0.04234456,  0.29627254,  0.4659822 ,  0.73550881],
       [ 0.22042888,  0.5562683 ,  0.99206868,  0.95697328]])
In [172]:
A.transpose()
Out[172]:
array([[ 0.48338662,  0.14395604,  0.75429594,  0.04234456,  0.22042888],
       [ 0.03486614,  0.35601808,  0.33171673,  0.29627254,  0.5562683 ],
       [ 0.35250375,  0.70903865,  0.99989876,  0.4659822 ,  0.99206868],
       [ 0.48956011,  0.9131345 ,  0.96116405,  0.73550881,  0.95697328]])
In [173]:
B=np.random.random(4)
np.dot(A,B)
Out[173]:
array([ 0.80753886,  1.00126195,  1.75597537,  0.65218053,  1.36082613])

Zugriff auf Elemente, Zeilen, Spalten mit Slice-Notation

In [174]:
A[1, 1]                         # Zeile, Spalte; Zählen ab 0
Out[174]:
0.3560180798205802
In [175]:
A[1, :]                         # Zeile 1
Out[175]:
array([ 0.14395604,  0.35601808,  0.70903865,  0.9131345 ])
In [176]:
A[:, 2:4]                       # Spalten 2 und 3 
Out[176]:
array([[ 0.35250375,  0.48956011],
       [ 0.70903865,  0.9131345 ],
       [ 0.99989876,  0.96116405],
       [ 0.4659822 ,  0.73550881],
       [ 0.99206868,  0.95697328]])

Lineare Algebra

In [177]:
A.trace()
Out[177]:
2.5748122616432552
In [178]:
D = np.random.random([5,5])
D
Out[178]:
array([[ 0.72258083,  0.49213584,  0.39029114,  0.13777797,  0.14733024],
       [ 0.49295046,  0.96244322,  0.90349252,  0.73571479,  0.7970654 ],
       [ 0.64442889,  0.79313952,  0.96435853,  0.93050668,  0.0633755 ],
       [ 0.8811195 ,  0.46305373,  0.20892729,  0.35398646,  0.42700248],
       [ 0.41150622,  0.83153176,  0.05982231,  0.28899535,  0.91271137]])

Viele Lineare-Algebra-Routinen in den Modulen numpy.linalg

In [179]:
np.linalg.det(D)
Out[179]:
-0.086852383652378906
In [180]:
D.shape, A.shape
Out[180]:
((5, 5), (5, 4))
In [181]:
x = np.linalg.solve(D, A)       # Löse D x = A
x
Out[181]:
array([[-0.10502766, -0.03973723, -0.16475521,  0.2558585 ],
       [ 1.98802613,  0.44465834,  1.85729453,  0.92906041],
       [-0.45310927, -0.6574316 , -1.16301222, -0.5999946 ],
       [-0.24520729,  0.68300015,  0.86041066,  0.69200525],
       [-1.41500226,  0.04910435, -0.72707929, -0.09307495]])
In [182]:
A2 = np.dot(D, x)
np.max(np.abs((A - A2)))
Out[182]:
3.3306690738754696e-16
In [183]:
Q,R = np.linalg.qr(D)
Q
Out[183]:
array([[-0.49555569,  0.27195606, -0.01421845,  0.75665767,  0.32822471],
       [-0.33807208, -0.59403718, -0.30505216,  0.25237931, -0.61324951],
       [-0.44195804, -0.19809221, -0.54035802, -0.45305015,  0.51787193],
       [-0.60428366,  0.50211579,  0.22703861, -0.38734578, -0.42560277],
       [-0.28221653, -0.53084738,  0.75047165, -0.09210139,  0.25858175]])
In [184]:
np.linalg.det(Q)
Out[184]:
1.0000000000000002
In [185]:
R
Out[185]:
array([[-1.45812234, -1.4342781 , -1.0681968 , -1.0237137 , -0.88609807],
       [ 0.        , -0.80391237, -0.54844885, -0.55956875, -0.71607908],
       [ 0.        ,  0.        , -0.70993104, -0.43194571,  0.50242327],
       [ 0.        ,  0.        ,  0.        , -0.29536828,  0.0344695 ],
       [ 0.        ,  0.        ,  0.        ,  0.        , -0.35334508]])

Dateien schreiben und lesen

Am einfachsten in Textdateien mit numpy:

In [186]:
np.savetxt("R.dat", R)
In [187]:
cat R.dat
-1.458122336744755776e+00 -1.434278100086884278e+00 -1.068196795057591686e+00 -1.023713702778334289e+00 -8.860980675368114179e-01
0.000000000000000000e+00 -8.039123679368845865e-01 -5.484488467379564636e-01 -5.595687460967161408e-01 -7.160790750152962181e-01
0.000000000000000000e+00 0.000000000000000000e+00 -7.099310385879507024e-01 -4.319457054633304427e-01 5.024232730372977240e-01
0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 -2.953682823235003196e-01 3.446949983850866595e-02
0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 -3.533450790583071432e-01
In [188]:
R2 = np.loadtxt("R.dat")
R2
Out[188]:
array([[-1.45812234, -1.4342781 , -1.0681968 , -1.0237137 , -0.88609807],
       [ 0.        , -0.80391237, -0.54844885, -0.55956875, -0.71607908],
       [ 0.        ,  0.        , -0.70993104, -0.43194571,  0.50242327],
       [ 0.        ,  0.        ,  0.        , -0.29536828,  0.0344695 ],
       [ 0.        ,  0.        ,  0.        ,  0.        , -0.35334508]])

Python-Bordmittel

In [189]:
with open('test.dat', 'w') as f: # with Block: Datei sicher geschlossen
    f.write('Test1\nTest2')
In [190]:
cat test.dat
Test1
Test2
In [191]:
with open('test.dat', 'r') as f:
    for n, l in enumerate(f.readlines()):
        print n, l.strip()
0 Test1
1 Test2

Matplotlib: einfach zu erlernde, aber mächtige Bibliothek für Plots

In [192]:
import numpy as np
import matplotlib.pyplot as plt

plt.figure(figsize=(10,6))

for d in [4, 20, 500]:
    x_values = np.linspace(0, 4, d)
    y_values = [ np.sqrt(x) for x in x_values ]   # äquivalent: y_values = np.sqrt(x_values)
    plt.plot(x_values, y_values, label=str(d))

plt.xlabel("x");
plt.ylabel("y");
plt.legend()

fig = plt.gcf()

plt.show()
In [193]:
fig.savefig("test.pdf")

2D-Plots

In [194]:
def f_plus(x,y):
    return np.sqrt(3+2*np.cos(np.sqrt(3)*y)+4*np.cos(x)*np.cos(np.sqrt(3)/2*y))

def f_minus(x,y):
    return -np.sqrt(3+2*np.cos(np.sqrt(3)*y)+4*np.cos(x)*np.cos(np.sqrt(3)/2*y))

X = np.arange(-3.14, 3.14, 0.1)
Y = np.arange(-3.14, 3.14, 0.1)

fig = plt.figure()
Z_plus = np.array([[f_plus(x,y) for x in X] for y in Y])
Z_minus = [[f_minus(x,y) for x in X] for y in Y]
plt.imshow(Z_plus)
plt.show()

3D-Darstellung

In [195]:
XX,YY = np.meshgrid(X,Y)
XX,YY
Out[195]:
(array([[-3.14, -3.04, -2.94, ...,  2.86,  2.96,  3.06],
       [-3.14, -3.04, -2.94, ...,  2.86,  2.96,  3.06],
       [-3.14, -3.04, -2.94, ...,  2.86,  2.96,  3.06],
       ..., 
       [-3.14, -3.04, -2.94, ...,  2.86,  2.96,  3.06],
       [-3.14, -3.04, -2.94, ...,  2.86,  2.96,  3.06],
       [-3.14, -3.04, -2.94, ...,  2.86,  2.96,  3.06]]),
 array([[-3.14, -3.14, -3.14, ..., -3.14, -3.14, -3.14],
       [-3.04, -3.04, -3.04, ..., -3.04, -3.04, -3.04],
       [-2.94, -2.94, -2.94, ..., -2.94, -2.94, -2.94],
       ..., 
       [ 2.86,  2.86,  2.86, ...,  2.86,  2.86,  2.86],
       [ 2.96,  2.96,  2.96, ...,  2.96,  2.96,  2.96],
       [ 3.06,  3.06,  3.06, ...,  3.06,  3.06,  3.06]]))
In [196]:
from mpl_toolkits.mplot3d import axes3d

XX,YY = np.meshgrid(X,Y)

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_wireframe(XX, YY, Z_plus, color='black')
ax.plot_wireframe(XX, YY, Z_minus, color='black')
plt.show()
In [197]:
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(XX, YY, Z_plus, cmap='jet', linewidth=0, antialiased=True, vmin=-3, vmax=3, rstride=1, cstride=1)
ax.plot_surface(XX, YY, Z_minus, cmap='jet', linewidth=0, antialiased=True,vmin=-3, vmax=3, rstride=1, cstride=1)
plt.show()