Letzter Update: 2009-07-25

KnowHow - Software - Python - Kurz

Ich mag die Dinge ultrakurz als Übersicht, setzt mindestens Python 2.4 voraus. Ab Python 2.5 gibt es wesentliche Verbesserungen bei Iteratoren, wodurch Coroutinen erst möglich werden.

Minimalprogramm

Ein kleines Python-Programm das einen guten Anfang abgibt:

#!/usr/bin/env python

def main(arg):
        print "Hello world and %s" % arg

if __name__=='__main__':
        import sys
        if (len(sys.argv)!=2):
                raise "Single argument please"
        main(sys.argv[1])

Typen

Python hat neben den normalen Typen auch viele "Collection"-artige Datentypen:
tuple   (1,)   immutabel (nicht der Inhalt, aber das tupel selbst)
list    [1]    mutabel
dict    {0:1}  mutabel

  • Tupel sind in der Regel schneller als Lists.
Wichtig: Man kann die einfach addieren:
(1,)+(2,)
[1]+[2]
aber nicht
{0:1}+{1:2}

Oft wird man folgendes Konstrukt finden:
args={'param':wert}
fn1(**args)
fn2(*args)
parms=(wert,)
fn3(*parms)
Das ist gleichwertig zu
fn1(param=wert)
fn2(wert)
fn3(wert)

Funktionen kennen notwendige (x), unbenannte (y) und benannte (z) parameter. Die notwendigen Parameter werden mit den unbenannten Parametern von vorne aufgefüllt, die unbenannten (y) bekommen alle weiteren unbenannten Parameter zugewiesen:
def test(x,*y,**z):
  print repr(x)
  print repr(y)
  print repr(z)

test(1,2,3)
test(1,a=1)
test(x=1)
aber nicht
test(1,x=2)
test(a=1)
test(y=(1,))
test(x=1,27)
Die Reihenfolge ist zu beachten, zuerst unbenannte, dann benannte. Und die bereits besetzten Keywörter kann man nicht überschreiben.

Immutable

Strings        "string" 'string'
Zahlen         (übliches)
Komplexe Zahl  1+2j complex(1,2)
Tupel          (1,) manchmal auch ohne Klammern schreibbar, aber: Der Inhalt kann mutabel sein!

"""multi       (ginge auch mit ')
line
strings"""

Spezial: Erster String (normalerweise Multi-Line) in Funktion/Modul etc. ist Variable __doc__

Immutable Sets

Frozensets sind spezielle Tupel die Werte nur einmal enthalten. Sie können nur Werte enthalten die immutable sind (d. h. unveränderlich), da sie selber unveränderlich sind. (s und t sind sets)

frozenset(list)                  Erzeuge ein Frozenset
s-t   s.difference(t)            Elemente die in s sind aber nicht in t (s ohne t)
s|t   s.union(t)                 Vereinigungsmenge: Elemente die in s oder t sind (aber nur einfach!)
s&t   s.intersection(t)          Schnittmenge: Elemente die sowohl in s als auch in t sind
s^t   s.symmetric_difference(t)  Vereinigung ohne Schnitt: (s|t)-(s&t)
s<=t  s.issubset(t)              s ist in t enthalten
s>=t  s.issuperset(t)            t ist in s enthalten
      s.copy()                   Flache Kopie

Werden Sets und Frozensets gemischt bestimmt der erste Operand (links) den Resultatstyp.

Mutable

List         [a,b]
Dictionary    {i1:v1, i2:v2}

set(list)                                   Erzeuge ein Set
s|=t      s.update(t)                       s=s|t
s&=t      s.intersection_update(t)          s=s&t
s-=t      s.difference_update(t)            s=s-t
s^=t      s.symmetric_difference_update(t)  s=s^t
s.add(x)                                    s=s|set([x])
s.remove(x)                                 s=s-set([x]) allerdings mit Exception KeyError wenn x nicht in s ist.
s.discard(x)                                s=s-set([x]) (ohne KeyError)
s.pop()                                     holt ein (beliebiges) Element aus s, KeyError wenn leere Liste
s.clear()                                   s=set()

Funktionen und Listen

Sets,Listen und Assoc sind Collections,

l=[1,2,3]            wenn unten verwendet war es vorher so gesetzt

x in l               Testet ob x in l enthalten ist
x not in l           Testet ob x nicht in l enthalten ist

complex(a,b).real=a  complex(a,b).imag=b
abs(complex(a,b))    "Länge" der komplexen Zahl: sqrt(a*a+b*b)
"hello"[1:2]         Ergibt "e", denn from:to index ab 0 und exklusive "to"
"hello"[-1]          "o" (vom Ende)
del var              funktioniert auch für del a[5]
"a"*3                "aaa"
"%03d" % 3           "003" (wie sprintf)

len("test")          4 strings sind eigentlich nur Listen aus Bytes
len((2,))            1 Anzahl der Elemente im Tupel
len([a,b])           2 Geht auch für Listen, etc.
l[1]=[5,6]           [1,[5,6],3] Extrahiert wurde die Zahl 2, Zuweisung an Element
l[1:2]=[5,6]         [1,5,6,3] Extrahiert wurde die Liste [2], Zuweisung an Liste
l[1:2]=(5,6)         [1,5,6,3] Listen sind austauschbar
l[1:2]="56"          [1,'5','6',3] Strings sind Listen!
l[1:1]               Leere Liste [], ebenso wie l[1:0]

range([a=0,]b[,s=1]) Liste aus Integer von a bis (ausschließlich) b mit inkrement s
                     for i in range(1,100,2)

list.append(x)       list.extend([x])
list.extend(x)       list[len(list):]=x
list.insert(i,x)     list[i:i]=[x]
list.remove(x)       del list[list.index(x)]
del list[i]          list[i:i+1]=[]
del list[i:j]        list[i:j]=[]  (also: del list[i:i] tut nix!)
pop([i=0])           hole element i und lösche es: pop() LIFO, pop(0) FIFO
list.index(x)        index von Element das x enthält, Fehler wenn keins
list.count(x)        Anzahl der Elemente die x enthalten
list.sort()          Sortieren (verändert list!) (sort fn?)
list.reverse()       Liste umdrehen (verändert list!)

filter(fn,list)      Liefert Liste der Elemente für die fn() nicht 0 ergibt
map(fn,list[,..])    Transformiert Liste per fn() (jagt alle Elemente durch fn und speichert das Ergebnis)
                     Mehrere (gleichlange) Listen angebbar für Funktion mit mehreren Argumenten
reduce(fn,l[,start]) x[len(l)] mit x[n]:=fn(l[n-1],x[n-1]) mit x[0]=start bzw. x[0]=l[0]
                     Funktion wird auf alle Elemente angewendet, wobei das Ergebnis immer wieder reingesteckt wird
                     Bei assoziativen Funktionen wie Summenbildung bekommt man leicht verständliche Ergebnisse

assoc.iteritems()    Itemiterator-Object für Dictionary für "for key,value in assoc..."
enumerate(list)      Enumerationsobjekt für "for index,value in enum.."
zip(l1,l2[,lx..])    Liste mit Tupeln für "for v1,v2[,vx..] in zip(..)"
reversed(list)       Liste rückwärts
sorted(list)         Liste sortiert, wobei die Liste nicht verändert wird

str(ob)              Lesbarer Output
repr(ob)             Code-Repräsentation so wie es Interpreter wieder schluckt
                     Auch: Backtick-Operator (aber nimmer verwenden!)

IO

f=open('name', 'r')
f.read([n])        N bytes lesen, wenn nicht da: alles!
f.readline()       Zeilenweise
for line in f:     Loop über die Zeilen (file ist iterierbar)

f.write(string)
f.seek(n)          Relativ zum Anfang (auch: f.seek(n,0))
f.seek(n,1)        Relativ zu momentan
f.seek(n,-2)       Relativ zum Ende
f.close()

Pickle siehe docs.python.org/ lib/ module-pickle.html
import pickle
import cPickle              Einfachere aber 1000 mal schnellere Variante in Maschinencode
pickle.dump(x,f)           Serialisieren
x = pickle.load(f)         Deserialisieren
s = pickle.dumps(x)        Direkt nach String wandeln
x = pickle.loads(s)        Und umgekehrt
  • Pickle kann nicht alle Objecte umwandeln, "instanceobject"-Klassen (gebundene Funktionen) gehen nicht (wie auch?).
  • Pickle kennt verschiedene Formate, sinnvoll sind eigentlich nur der default (0, Rückwärtskompatibel) und pickle.HIGHEST_PROTOCOL (braucht mindestens dieselbe Python-Version).
  • Siehe __getinitargs__ bei Klassen.

Syntax

if expr: [expr]      Man kann gleich hinter dem : weiterschreiben
elif expr:
else:                Else geht auch für for/while, wird aber bei break übersprungen
while expr:

for a in list                 Iteriere über Elemente
for k,v in assoc.iteritems(): Iteriere über Key/Value
for i,v in enumerate(list):   Iteriere über Index/Value

break / continue     wie in C, aber beachte else: das bei break nicht ausgeführt wird
pass                 NOP
def func(args):      *name = unnamed / **name = assoc / benannt und initialisiert
return [wert]        Oder letztes Ergebnis der Funktion
func(*l) func(**a)   listen bzw. assoziative Arrays (in Python Dictionary genannt) liefern args

lambda args: expr    Anonyme Funktion

l = a,b,c            "Tupel packing" laut Python, weist erzeugtes Tupel zu
a,b,c = l            Übliches Dekompositing einer Liste ("sequence unpacking" laut Python Doc)

[expr for v in list if expr [..]]
                     Listen-Konstruktor.  Expr kann z. B. Tupel etc. sein.  Mehrere for/if gehen (verschiedene Vars)

a < b < c            a < b and b < c
and / or             shortcut-evaluation!
l1 < l2              bei Listen rekursiv und logisch.
string < list        Verschiedene Datentypen unlogisch (momentan: Typname wird verglichen)

string.ljust(n)  string.rjust(n)  string.center(n)  string.zfill(n)
                     letzteres für Zahlen, 0-padding mit Vorzeichenregel (etwas krank!)

try: statement       Bei Fehler -> except
except type:         type kann Tupel sein für mehrere, oder fehlend bei letzter für catchall
else:                Block der ausgeführt wird wenn keine Exception auftrag
finally:             Cleanup, wird immer ausgeführt (auch bei break, continue, return)

Ab Python 2.6:
with expr as var:    Variable existiert nur innerhalb des "with".  Danach wird sie zerstört.
                     Files werden beim zerstören der Variable geschlossen.  With hilft dabei.

Python 2.5:
from __future__ import with_statement
                     Macht es in python 2.5 verfügbar, "KEYWORD" ist z. B. "with".

Beispiel einer typischen Exception:
class MyError(Exception):
    def __init__(self, value):
        self.value = value
    def __str__(self):
        return repr(self.value)
Geklaut bei docs.python.org/3.0/tutorial/errors.html

Hier ein Beispiel für eine generische Exception:
def test(s):
  raise Exception(s)

try:
  test("test")
except Exception, p:
  print("Exception cought: %s" % repr(p))

With-Decorator

Siehe www.python.org/dev/peps/pep-0343/

Module

dir()               Alle bekannten Module
dir(modul)          Inhalt vom Modul

import modul        Namen als modul.element ansprechen
from modul import name,..
from modul import * Elemente kann man direkt ansprechen (importiert keine _-Namen)

modul.__doc__       Ist der Doc-String

.py Files werden automatisch in .pyc oder .pyo (-O) übersetzt. -O ist brauchbar -> assert-Statements werden wegoptimiert, bei -OO auch __doc__ (was nix bringt)

Packages

__init__.py         Im Verzeichnis, damit der Pfad gefunden wird
from .. import xxx  Interne Paketbezüge.  Enthält Modul aber __main__ dann so nicht!

__path__            Enthält den Include-Pfad, abändern um Unterpakete anderswo zu finden (besser nicht!)

Klassen

  • Python macht immer Pass-By-Reference: Änderungen am Übergabeparameter sieht der Auffrufer! Bei "immutable" Typen (Strings, Zahlen, siehe oben bei Typen) erzeugt man dadurch ein neues Objekt, das somit den Aufrufer nicht erreicht. Das gilt allgemein, nicht nur beim Aufruf einer Funktion oder Methode.
  • Member-Funktionen bekommen das Object als ersten Parameter: Konvention ist, das Object "self" zu nennen. Theoretisch aber kann jede Funktion als Member herhalten (zuweisbar).
"def"s sind im folgenden immer innerhalb der Klasse!
class NAME
class NAME(BASE)
class NAME(BASE1,..)

__ATTR__                     internal names, reserviert
__ATTR_, __ATTR             class private, umgewandelt in __NAME__ATTR bzw. __NAME__ATTR
                             Nicht von anderen Klassen aus aufrufbar, da NAME immer die aktuelle Klasse ist.
                             Deshalb auch keine Vererbung dieser Namen.

NAME.__doc__                 Üblicher __doc__ string.
NAME.__name__                NAME
NAME.__dict__                Attributs-Collection (genauen Typ muss ich noch rausfinden)

def __init__(self):         Initialisierungsfunktion
c=NAME()                     Erzeugen eines Klassenobjekts (kein "new" notwendig!)
def __init__(self, args):  
c=NAME(args)                 Erzeugen eines Klassenobjekts mit Parametern

c.ATTR = wert                Attribut Zuweisen, das geht beliebig (neu, daten, methoden, selbst Base-Klasse)
c.FN()                       NAME.FN(c) auf
c.FN(args)                   NAME.FN(c,args)
f = c.FN                     Ist ATTR eine methode (Funktion) wird automatisch "c" mitgespeichert
f()                          Implizit NAME.FN(c)  (wie komme ich wieder von f auf c?  Geht vermutlich irgendwie)

pickle/copy:
def __getinitargs__(self):  Aufgrerufen von pickle: __init__ mit gegebenen Tupel beim unpickle aufrufen
                             Fehlt das, wird __init__ gar nicht aufgerufen!
def __getstate__(self):     Pickle verwendet Rückgabe anstelle von __dict__
def __setstate__(self,o):   Unpickle setzt so die Werte wieder.
                             Fehlt __setstate__ muss __getstate__ einen __dict__ typ zurückgeben

c.__class__                  Klassenobjekt, für alle Klassenobjekte gleich
__reduce__, __reduce_ex__   Siehe Online-Hilfe zu pickle
__copy__ __deepcopy__       Siehe Online-Hilfe zu copy

Iteratoren und Generatoren

Iteratoren:
Zu iterierende Klasse:
def __iter__(self)          Iterator der Klasse abrufen.  Liefert ein Iterierbares Objekt.  Kann das Objekt selber sein!
                             iter(x) ist eine Abkürzung für x.__iter__()

Iterator-Objekt:
def next(self):             Nächsten Eintrag des Iterators abrufen

Generatoren:
def generator(args):
  ...
  yield wert
  ...
implizites raise StopIteration am Ende

PEP342 für Python 2.5:
yield                       yield None

Iterator-Objekt:
def send(self, v):          Wert an den letzten yield senden und nächsten yield abrufen
                             iterator.send(None) ist dasselbe wie iterator.next()
def close(self):            Wird beim schließen des Iterators aufgerufen, im Wesentlichen:
                             self.throw(GeneratorExit) 
def throw(self, type, value=None, traceback=None):
                             yield wird unterbrochen mit: raise type, value, traceback
def __del__(self):          Ruft bei der Garbage-Collection self.close() auf.

def generator(args):
  ...
  v=(yield w)
  ...
try .. catch .. finally wird somit ab Python 2.5 auch in Iteratoren unterstützt. Python 2.4 kann es nicht.

Consumer-Decorator

Siehe www.python.org/dev/peps/pep-0342/

Library

docs.python.org/lib/

TBD

Weiteres

Dekoratoren:

@classmethod
@staticmethod

Spezielle Dinge:
class.__metaclass__
Siehe www.ibm.com/developerworks/linux/library/l-pymeta2/

Funktionsaufrufe

apply(function, args)    Dasselbe wie function(*args) bzw. function(*args, **kw)
function.__call__(args)  Langform von function(args)