next up previous
Next: Kontrollstrukturen Up: python Previous: python

Unterabschnitte

Einführung

Geschichte von Python

Python wurde 1989 von Guido von Rossum in den Niederlanden erfunden. Es ist nach der Comedytruppe ,,Monty Python'' benannt, weshalb in Beispielen nicht die traditionellen Variablennamen ,,foo'' und ,,bar'' verwendet werden, sondern Wörter aus den Sketchen wie ,,spam'' oder ,,eggs''. Dieser Tradition möchte ich mich anschließen.

Python ist eine mächtige, objektorientierte Skriptsprache mit Garbage Collector, aber dennoch einfach zu benutzen. Es gibt viele Libraries sowie eine in den Newsgruppen comp.lang.python.* und im Internet http://www.python.org aktive Benutzergemeinde.

Syntax

Die Syntax von Python ist sehr einfach: manche Leute bezeichnen es als Pseudocode, der läuft. Um Blöcke kenntlich zu machen, gibt es keine geschweiften Klammern wie in C oder Java, allein die Einrücktiefe zählt: alles, was auf einer Ebene eingerückt ist, gehört zu einem Block. Nach Vokabeln, die Blöcke einleiten, wie if, for etc. steht ein Doppelpunkt. Das Kommentarzeichen ist # - alles danach bis zum Ende der Zeile ist ein Kommentar.

Es gibt die folgenden Operatoren: (die Tablle ist nach Vorrang geordnet, d. h. die Operatoren mit niedrigstem Vorrang stehen oben)

Operatoren Beschreibung
x or y Logisches Oder
lambda args: expr Anonyme Funktion
x and y Logisches Und
not x Logische Verneinung
<, <=, >, >=, ==, <>, != Vergleichsoperatoren
is, is not Identitätstests
in, not in Teil einer Sequenz
x | y Bitweises Oder
x ^ y Bitweises exklusives Oder
x & y Bitweises Und
x << y, x >> y Bitshifts
x + y, x - y Addition / Verknüpfung, Substraktion
x * y, x / y, x comment_mark>14 Formatierung  
-x, +x, ~x Unäre Negation, Identität, Bitweises Komplement
x[i], x[i:j], x.y, x(...) Indexierung, Slicing, Qualifizierung, Funktionsaufruf
(...), [...], {...}, `...` Tupel, Liste, Dictionary, Stringkonvertierung

Natürlich sollte man, wie in anderen Sprachen auch, lieber Klammern setzen, um die Lesbarkeit zu erhöhen.

An Zahlentypen gibt es int, die durch C Integers, und float, die durch C Doubles implementiert sind. Deshalb ist auch der Wertebereich, wie in C, nicht genau definiert: man weiß nur die Mindestgröße. Oktale und Hexadezimal-Schreibweise funktionieren wie in C (mit 0 bzw. 0x am Anfang). Außerdem gibt es extra große Integer, die nur durch den Speicher begrenzt sind, sowie komplexe Zahlen (Schreibweise: 3+4j). Die Typumwandlung beim Rechnen mit Zahlen von verschiedenen Typen ist auch wie in C: das Ergebenis ist vom ,,komplexeren'' Typ der beiden Operanden.

Wie in Java gibt es keine Zeiger oder Operationen für ihre Manipulation, allerdings kann man bei Vergleichen auf gleichen Inhalt der Speicherzelle bzw. gleiche Speicherzelle testen. Die Vokablen dafür sind allerdings genau umgekehrt wie in Java: dort gibt es equals() bzw. ==, in Python heißen diese Operationen == bzw. is. Es gibt keinen extra Typ für wahr und falsch: alles, was nicht falsch ist, ist wahr, und falsch sind 0, der leere String '', leere Tupel, Listen und Dictionaries ((), [], {}) sowie None, was null in Java entspricht.

Der Lesbarkeit wegen gibt es weder die Operatoren +=, -= etc. noch ++ oder --. Allerdings kann man --a schon sagen: das ist das Inverse zum Inversen von a, also a.

Datentypen und ihre Operationen

Der Vergleich von Datentypen erfolgt bei Zahlen über ihre relative Größe, bei Strings nach ASCII-Ordnung, Bei Listen und Tupeln werden von links nach rechts die einzelnen Komponenten miteinander verglichen. Dictionaries werden als sortierte Key-Value-Paare miteinander verglichen. Anstelle von a > 0 and a <= 100 kann man auch 0 < a <= 100 schreiben.

Zuweisungen an Variablen gehen in Python auf verschiedene Weise:

        spam = 'Spam'
        spam, eggs = 'yum', 'YUM'
        [spam, eggs, ham] = ['yum', 'YUM', 'meat']
        spam = ham = 'lunch'
        spam, eggs, pie = 'Spam', ['eggs', 4], 3.1415
Wenn auf der rechten Seite des Gleichheitszeichens mehrere Werte stehen, werden diese von Python erst in ein Tupel verpackt und dann an die Variablen auf der linken Seite zugewiesen - deshalb nennt man diesen Vorgang auch ,,tuple unpacking''. Bei Variablennamen sind Groß- und Kleinschreibung wichtig: spam ist etwas anderes als Spam. Variablennamen dürfen mit einem Buchstaben oder einem Unterstrich beginnen, danach sind Buchstaben, Zahlen und Unterstriche erlaubt.

Für fast alle Datentypen gibt es einige gemeinsame Operationen, so die Länge, 1 die Position eines Elements, die Aneinanderfügung von 2 gleichen Datentypen, die Wiederholung des Elements, sowie die Mitgliedschaft in Sequenzen. Das Umwandeln in andere (ähnliche 2 ) Datentypen funktioniert, indem man den Namen des Datentyps, den man erhalten möchte, auf das Element anwendet.

Mit print kann man Elemente ausgeben, und wie in Perl kann man auch die Klammern um die Argumente weglassen. Als Argument bekommt print entweder einen String mit + zusammengefügt, oder mehrere Argumente durch Kommas getrennt - dann werden sie bei der Ausgabe mit Leerzeichen getrennt.

        >>> len('spam') #Länge
        4
        >>> 'spam'[3] #Position
        'm'
        >>> 'spam' + 'eggs' #Konkatenation
        'spameggs'
        >>> 4 * 'Ni! ' #Wiederholung
        'Ni! Ni! Ni! Ni! '
        >>> 'a' in 'spam' #Mitgliedschaft
        1
        >>> 'o' in 'spam' #Mitgliedschaft
        0
        >>> tuple([1, 2, 3]) #Umwandlungen
        (1, 2, 3)
        >>> tuple('hallo')
        ('h', 'a', 'l', 'l', 'o')
        >>> list('hallo')
        ['h', 'a', 'l', 'l', 'o']
        >>> str(1)
        '1'
        >>> int('1')
        1

Indexing und Slicing

Strings (und andere Sequenzen) gehen von Position 0 bis zur Position Länge des Strings - 1. Um an das Element an der i-ten Stelle zu gelangen, verwendet man die Index-Schreibweise: a[i]. Man kann allerdings auch Offsets, negative Längenangaben, als Index angeben: a[-i] ist das gleiche wie a[len(a) - i]. Mithilfe von ,,Slicing'' (in Scheibchen schneiden) kann man sich auch Abschnitte holen oder belegen. Dafür wird die Doppelpunktnotation verwendet: a[i:j] liefert a ab Position i bis vor Position j. Schreibt man nichts vor bzw. hinter den Doppelpunkt, geht die Sequenz vom Anfang bzw. bis zum Ende. Auch beim Slicing kann man Offsets benutzen.

          >>> s = 'lumberjack'
          >>> s[5]
          'r'
          >>> s[-1]
          'k'
          >>> s[2:4]
          'mb'
          >>> s[:6]
          'lumber'
          >>> s[7:]
          'ack'
          >>> s[6:-1]
          'jac'

Abbildung 1: Slicing
\includegraphics[angle=0,width=14cm]{slice.eps}

Unveränderliche Datentypen: Tupel und Strings

Zu den unveränderliche Datentypen gehören Tupel und Strings. Man kann sie als Schlüssel in Dictionaries benutzen, aber nicht in sich verändern, wie sortieren, umdrehen, oder einzelnen Positionen bzw. Slices etwas zuordnen.

Tupel sind unveränderliche Listen. () bezeichnet ein leeres Tupel. Die Schreibweise tupel = (1,) für ein einstelliges Tupel ist zwar etwas seltsam mit dem Komma am Ende, aber sonst würden die Klammern als Vorrangoperator aufgefaßt. Größere Tupel erhält man, indem man die Elemente einfach in Klammern einschließt. Man kann verschiedene Typen in ein Tupel packen, sogar Tupel. Auf Tupeln funktionieren die schon besprochenen Operationen wie Indexing, Slicing, Wiederholung, etc.

            >>> t1 = (4, )
            >>> t2 = ('a', t1, (3, 'hallo'))
            >>> t1
            (4,)
            >>> t2
            ('a', (4,), (3, 'hallo'))
            >>> t2[1][0]
            4
            >>> t2[:-1] 
            ('a', (4,))
            >>> t2[1:][0]
            (4,)
            >>> t2[1:][1]
            (3, 'hallo')

Strings sind der zweite unveränderliche Datentyp. Bis auf die Notation (Strings umschließt man mit '' oder "") verhalten sie sich wie Tupel. Die zwei Arten von Anführungszeichen sind als Bequemlichkeit da, damit man in "Guido's" den einfachen Quote ' nicht mit dem Backslash zu maskieren braucht. Benutzt man Dreifach-Quotes, können die Strings über mehrere Zeilen hinweg gehen, Newlines werden erhalten.

Man kann in Strings, ähnlich wie in C, mit dem Prozentzeichen eine Formatierung erzielen. Im String benutzt man die aus printf bekannten Platzhalter. Vor den Werten, die in einem Tupel stehen müssen, wird das Prozentzeichen dann als Operator benutzt, der anzeigt, daß die Werte folgen. Im Modul string gibt es auch noch andere Funktionen zur Stringmodifikation, wie upper(), find() etc.

             >>> long_string = """hallo
             ... dies ist die zweite Zeile
             ... 3"""
             >>>'%e %f %g' %(1.1, 2.2, 3.3)
'1.100000e+00 2.200000 3.3'

Veränderbare Datentypen: Listen und Dictionaries

Listen in Python können von beliebiger Länge sein und, wie Tupel, beliebige Objekte aufnehmen. Man kann auch zyklische Listen erstellen, wobei die Ausgabe diese verkürzt anzeigt. Wie alle veränderlichen Datentypen werden Listen als Referenzen übergeben (,,call by reference''). [] ist die leere Liste, auch sonst werden Listen in eckige Klammern eingeschlossen. Bei Listen gibt es zusätzlich zu den erwähnten Operationen noch append() zum Anfügen eines Elements, sort() und reverse(), die die Liste destruktiv sortieren bzw. umdrehen, sowie index(), das einem die Position des übergebenen Elementes sagt, und del, dem man die in der Liste zu löschende Position in der Index-Schreibweise übergibt.

          >>> a = [1, 4, 'spam', 3.14, 'Ni!']
          >>> a.sort()
          >>> a
          [1, 3.14, 4, 'Ni!', 'spam']
          >>> a.reverse()
          >>> a 
          ['spam', 'Ni!', 4, 3.14, 1]
          >>> a[2] = 'eggs'
          >>> a
          ['spam', 'Ni!', 'eggs', 3.14, 1]
          >>> a.index(4)
          Traceback (innermost last):
          File "<stdin>", line 1, in ?
          ValueError: list.index(x): x not in list
          >>> a.index('eggs')
          2
          >>> del(a[1])
          >>> a
          ['spam', 'eggs', 3.14, 1]

In Python bezeichnet man als Dictionaries das, was man aus Java als Hashtable oder aus awk als assoziatives Array kennt. Die abgelegten Objekte können verändert werden. Ein leerer Dictionary ist {}, die Schreibweise für eine bestimmte Zuweisung ist dict = {'schluessel1': 'wert1', 'schluesseln': 'wertn'}. Will man auf Werte zugreifen, so macht man dies mit der Index-Notation, gibt aber den Schlüssel als Index an, so z. B. dict['schluessel1']. Mit der Index-Schreibweise kann man Werte verändern oder auch neue ablegen. Dictionaries kann man nicht slicen, man kann aber die Funktionen len() und del auf sie anwenden. Auch die Überprüfung auf Mitgliedschaft mit in funktioniert nicht, es gibt aber has_key(), das abfragt, ob der Dictionary das Argument als Schlüssel enthält, sowie die Funktionen keys() und values(), die Sequenzen der Schlüssel bzw. Werte zurückliefern.

            >>> d = {'spam' : 2, 'eggs' : 3}
            >>> d
            {'spam': 2, 'eggs': 3}
            >>> d['sub'] = {'john': 'cleese', 'rowan': 'atkinson'}
            >>> d
            {'spam': 2, 'eggs': 3, 'sub': {'john': 'cleese', 'rowan': 'atkinson'}}
            >>> d['sub']['john'] = 'smith'
            >>> d
            {'spam': 2, 'eggs': 3, 'sub': {'john': 'smith', 'rowan': 'atkinson'}}
            >>> d.has_key('john')
            0
            >>> d['sub'].has_key('john')
            1
            >>> d.keys()
            ['spam', 'eggs', 'sub']
            >>> len(d)
            3

Noch ein eingebauter Datentyp: Files

Der letzte eingebaute Datentyp unterscheidet sich von den anderen dadurch, daß er keine Sequenz ist. Aber der Dateizugriff ist auch so ganz nützlich. Mit der Funktion open(), die Parameter wie in C bekommt, also den Dateinamen und die Zugriffsart ('r' für lesend, 'w' für schreiben, 'a' für anhängend), erhält man ein Filehandle. Dieses kann man jetzt je nach Zugriffsart lesen: mit read(), was die ganze Datei in einem String liefert, readlines(), was eine Liste mit den Zeilen der Datei liefert, readline(), was jeweils die nächste Zeile liefert, sowie read(N), was die nächsten N Bytes zurückgibt. Für schreibende Filehandles gibt es die Funktionen write(), die den übergebenen String in die Datei schreibt, sowie writelines(), die eine Liste von Strings erwartet und sie alle in die Datei schreibt. Allgemein kann man Filehandles mit close() schließen, mit flush() die Ausgabe erzwingen und mit seek() in der Datei herumwandern.

          >>> a = ["I'm a lumberjack and I'm okay\n", 
          ...'I drink all night and I work all day\n', 
          ...'(3, 4)\n', '3.1415\n']
          >>> output = open('/tmp/spam', 'w')
          >>> output.writelines(a)
          >>> output.write('hallo\n')
          >>> output.close()
          >>> input = open('/tmp/spam', 'r')
          >>> line = input.readline()
          >>> line
          "I'm a lumberjack and I'm okay\012"
          >>> line = input.readline()
          >>> line
	  'I drink all night and I work all day\012'
          >>> five_bytes = input.read(5)
          >>> five_bytes
          '(3, 4'
          >>> input.readlines()
          [')\012', '3.1415\012', 'hallo\012']
          >>> input.close()



Fußnoten

... Länge,1
Anders als andere Operationen auf Sequenzen wie sort(), reverse() etc. sind len() und del() keine Objektmethoden, sondern anscheinend Funktionen, die auf Datentypen angewendet werden.
... (ähnliche2
z.B. Umwandlung von Zahlen in Strings, Strings in Zahlen, Sequenzen(Listen, Tupel, Strings) ineinander

next up previous
Next: Kontrollstrukturen Up: python Previous: python
Britta Koch