################################ Datentypen ################################ Numerische Datentypen ====================== Numerische Datentypen sind: * für ganze Zahlen: ``int`` und ``long`` * für Gleitkommazahlen: ``float`` * für komplexe Zahlen: ``complex`` * für boolsche Werte: ``bool`` **Beispiele:** >>> x=3 >>> type(x) >>> x=3.0 >>> type(x) >>> x=1+2j >>> type(x) >>> x.real 1.0 >>> x.imag 2.0 >>> x.conjugate() (1-2j) >>> x=0 >>> y=1 >>> bool(x) False >>> bool(y) True >>> bool(1+1j) True >>> bool(0+0j) False Gleitkommazahlen vom Typ ``float`` können auch in exponentieller Form eingegeben werden, z.B. ``2e5`` für ``200000`` oder ``1e-3`` für ``0.001`` .. _labelOperatoren: Arithmetische Operatoren: ------------------------- Für numerische Datentypen sind folgende arithmetische Operatoren definiert: * Addition: ``x+y`` * Subtraktion: ``x-y`` * Multiplikation: ``x*y`` * Division: ``x/y`` * Rest beim ganzzahligen Teilen: ``x%y`` * Ganzzahliger Anteil der Integer Division: ``x//y`` * Potenzieren: ``x**y`` * Negatives Vorzeichen: ``-x`` In Python gibt es **keine** Operatoren für das Inkrementieren (``x++``) und Dekrementieren (``x--``). Es sind jedoch sogenannte *erweiterte Zuweisungen* der Form ``x+=y`` als kürzere Form für ``x=x+y`` möglich. **Beispiele:** >>> 3+5 8 >>> 5-7 -2 >>> 5*9 45 >>> 10%3 1 >>> 10//3 3 >>> 10/3 3 >>> 10/3.0 3.3333333333333335 >>> 2**12 4096 >>> -5 -5 Vergleichsoperatoren: --------------------- Für die Datentypen ``int``, ``long``, ``float`` und ``bool`` sind die Vergleichsoperartoren ``==``, ``!=``, ``<``, ``<=``, ``>`` und ``>=`` anwendbar. Umwandlung zwischen numerischen Datentypen: -------------------------------------------- Umwandlungen eines zu konvertierenden Werts ``x`` in einen neuen Typ werden allgemein in der Form ``neuerTyp(x)`` geschrieben, z.B. ``int(x)``, ``long(x)`` usw. Hier einige Beispiele: >>> x=3 >>> float(x) 3.0 >>> x=3L >>> type(x) >>> x=3.9 >>> int(x) 3 >>> complex(x) (3.9+0j) >>> bool(x) True Oktal- und Hexadezimaldarstellung ---------------------------------- Ganze Zahlen vom Typ ``int`` oder ``long`` können auch oktal oder hexadezimal eingegeben werden. Oktale Eingaben werden durch eine führende ``0``, hexadezimale Eingaben durch ein führendes ``0x`` identifiziert. **Beispiele:** >>> o=077 >>> o 63 >>> h=0x1A >>> h 26 >>> type(h) Für die Binärdarstellung von Zahlen gibt es in Python keine explizite Eingabemöglichkeit. Jedoch sind für beliebige ganze Zahlen ``x`` und ``y`` die Bitoperationen * ``x&y`` : Bitweise UND Verknüpfung * ``x|y`` : Bitweise ODER Verknüpfung * ``x^y`` : Bitweise EXOR Verknüpfung * ``x<>> l1=[2,'d',3.7,'letzte'] >>> l1 [2, 'd', 3.7000000000000002, 'letzte'] >>> type(l1) >>> type(l1[0]),type(l1[1]) (, ) >>> l1[1]=1020 >>> l1 [2, 1020, 3.7000000000000002, 'letzte'] Da die Liste ein sequenzieller Datentyp ist, können auf Instanzen diesen Typs alle in :ref:`Operatoren für Sequenzen ` definierten Operationen angewandt werden. Zusätzlich zu den dort genannten Operatoren, sind für Listen folgende definiert: * ``s[i]=x`` das i-te Element der Liste s wird durch x ersetzt, * ``s[i:j]=t`` der Ausschnitt von Element i bis Element j wird durch t ersetzt * ``s[i:j:k]=t`` die Elemente von ``s[i:j:k]`` werden durch t ersetzt, * ``del s[i]`` das i.te Element wird aus s entfernt * ``del s[i:j]`` die Elemente ``s[i:j]`` werden aus s entfernt * ``del s[i:j:k]`` die Elemente ``s[i:j:k]`` werden aus s entfernt **Beispiele für Operationen auf Listen:** >>> l2=[0,1,2,3,4,5,6,7,8,9] >>> l2 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> len(l2) 10 >>> min(l2) 0 >>> max(l2) 9 >>> l3=l2[1:8:3] >>> l3 [1, 4, 7] >>> l2[9]=l3 >>> l2 [0, 1, 2, 3, 4, 5, 6, 7, 8, [1, 4, 7]] >>> l2[1:3]=l3 >>> l2 [0, 1, 4, 7, 3, 4, 5, 6, 7, 8, [1, 4, 7]] >>> len(l2) 11 >>> del l2[-1] >>> l2 [0, 1, 4, 7, 3, 4, 5, 6, 7, 8] >>> del l2[5] >>> l2 [0, 1, 4, 7, 3, 5, 6, 7, 8] Ist ``L`` eine Liste, dann wird durch ``C=L`` eine Kopie der Referenz auf die Liste, auf welche ``L`` zeigt, angelegt. D.h. ``C`` zeigt auf den gleichen Speicher wie ``L``, jedoch werden nicht die Listenelemente kopiert. Es handelt sich also um eine **flache Kopie**. Eine tiefe Kopie einer Liste kann mit ``C=L[:]`` angelegt werden. Um tiefe Kopien von allgemeinen Objekten zu erstellen kann die Funktion ``copy.deepcopy()`` aus dem Paket ``copy`` verwendet werden (das Paket muss zuvor importiert werden). Listen können nicht nur mit den genannten Operationen manipuliert werden. Für Referenzen auf Listen können auch **Methoden** aufgerufen werden. Es sei s eine Referenz auf ein Objekt des Typs Liste. Die auf s anwendbaren Methoden sind dann: .. method:: s.append(x) hängt x an das Ende der Liste an, .. method:: s.extend(x) hängt die Elemente von x an das Ende der Liste an, .. method:: s.count(x) zählt wie häufig das Element x in s vorkommt, .. method:: s.index(x) liefert den Index an dem der Wert x erstmalig in s auftritt, .. method:: s.insert(i,x) fügt x am Index i in s ein, .. method:: s.pop(i) liefert das i.te Element der Liste und entfernt es aus dieser. Ohne Argument wird einfach das letzte Element herausgenommen, .. method:: s.remove(x) entfernt das erste Vorkommen von x aus s, .. method:: s.reverse() Kehrt die Reihenfolge der Elemente in s um, .. method:: s.sort() sortiert Liste nach aufsteigenden Werten. Mit ``s.sort(reverse=True)`` wird Liste absteigend sortiert. **Beispiele für Methoden auf Listen:** >>> s=[5,3,4,8,2,1,3,3,4,2] >>> s [5, 3, 4, 8, 2, 1, 3, 3, 4, 2] >>> x=[1,2,3] >>> x [1, 2, 3] >>> s.append(x) >>> s [5, 3, 4, 8, 2, 1, 3, 3, 4, 2, [1, 2, 3]] >>> s.pop() [1, 2, 3] >>> s [5, 3, 4, 8, 2, 1, 3, 3, 4, 2] >>> s.extend(x) >>> s [5, 3, 4, 8, 2, 1, 3, 3, 4, 2, 1, 2, 3] >>> s.index(4) 2 >>> s.insert(1,9) >>> s [5, 9, 3, 4, 8, 2, 1, 3, 3, 4, 2, 1, 2, 3] >>> s.reverse() >>> s [3, 2, 1, 2, 4, 3, 3, 1, 2, 8, 4, 3, 9, 5] >>> s.sort(reverse=True) >>> s [9, 8, 5, 4, 4, 3, 3, 3, 3, 2, 2, 2, 1, 1] Listen mit ganzen Zahlen ^^^^^^^^^^^^^^^^^^^^^^^^^^ Mit der ``range()`` Methode kann eine Liste von ganzen Zahlen effizient erzeugt werden. Derartige Listen werden besonders häufig in :ref:`for-Schleifen ` als Objekt, über dessen Elemente die Zählvariable iteriert, eingesetzt. Die Definition der Range Funktion ist .. function:: range(start,stop,step) Alle drei Argumente müssen ganze Zahlen sein. Die Argumente start und step sind optional. Die Funktion liefert eine Liste, deren Elemente ganze Zahlen von start bis stop in der Schrittweite step sind. Wird step nicht angegeben, dann ist die Schrittweite 1. Wird start nicht angegeben, dann ist der Startwert 0. Beispiel: >>> l=range(3,9,2) >>> l [3, 5, 7] Zweidimensionale Listen ^^^^^^^^^^^^^^^^^^^^^^^^ Da Listen Elemente beliebigen Typs enthalten können, ist es natürlich auch möglich Listen als Listenelemente zu benutzen. Damit lassen sich mehrdimensionale Arrays realisieren. Wie folgendes Beispiel zeigt: >>> matrix= [ ... [1,2,3], ... [4,5,6], ... [7,8,9] ... ] >>> matrix [[1, 2, 3], [4, 5, 6], [7, 8, 9]] Auf einzelne Elemente und auf ganze Zeilen des Arrays kann wie folgt zugegriffen werden: >>> matrix[0][2] 3 >>> matrix[0] [1, 2, 3] >>> matrix[0:2] [[1, 2, 3], [4, 5, 6]] Der Zugriff auf Spalten ist nur indirekt möglich: >>> col1=[matrix[i][1] for i in range(len(matrix))] >>> col1 [2, 5, 8] Tuple ------ Auf Listen können wie oben gezeigt relativ viele Operationen und Methoden ausgeführt werden. Diese Vielfalt bedingt jedoch auch einen relativ hohen Aufwand an notwendiger Rechenleistung. Falls die Vielfalt in der Modifikation gar nicht benötigt wird, jedoch auf Recheneffizienz zu achten ist, bietet sich der sequenzielle Datentyp Tuple an. Im Gegensatz zu Listen sind Tuple **immutable**, sie können also nach dem Erzeugen nicht mehr verändert werden. Genauer: Beim Erzeugen eines Tuple werden die Element-Referenzen festgelegt, die sich danach nicht mehr ändern können. Verweist jedoch eine Referenz auf ein Objekt vom Typ mutable, und ändert sich dieses Objekt, dann ändert sich auch der Inhalt der Liste. Tuple werden nicht mit eckigen, sondern mit runden Klammern angelegt. Der Zugriff auf einzelne Elemente wird jedoch wie im Fall der Listen mit eckigen Klammern realisiert. Lässt man die umschliessenden Klammern weg, wird die Sequenz aus mit Komma getrennten Elementen inherent als Tuple angelegt.: >>> t=(3,6,1,2,8,1) >>> t[2] 1 >>> t[3]=0 Traceback (most recent call last): File "", line 1, in TypeError: 'tuple' object does not support item assignment >>> x=[1,3,2,3] >>> r=x,3 >>> r ([1, 3, 2, 3], 3) >>> x.reverse() >>> r ([3, 2, 3, 1], 3) String ------- Strings sind sequenzielle Datentypen, deren Elemente Characters sind. Auf Strings können deshalb alle in :ref:`Operatoren für Sequenzen ` definierten Operationen angewandt werden. Strings können in Python vom Typ ``str`` oder ``unicode`` sein. In dieser Einführung wird nur der Typ ``str`` behandelt. Ein String wird erzeugt indem eine Zeichenkette (ohne Zeilenumbruch) innerhalb von doppelten oder einfachen Hochkommata geschrieben wird: >>> s1="Name Vorname" >>> s1 'Name Vorname' >>> s2='Strasse Hausnummer' >>> s2 'Strasse Hausnummer' Soll ein sich über mehrere Zeilen erstreckender String angelegt werden, ist die Zeichenkette innerhalb von dreifachen Hochkommata (doppelt oder einfach) zu schreiben. Stehen mehrere Strings unmittelbar oder durch Leerzeichen getrennt hintereinander, dann werden diese zu einem String zusammengefasst: >>> s3='''erste zeile ... zweite zeile ... dritte zeile''' >>> s3 'erste zeile\nzweite zeile\ndritte zeile' >>> print s3 erste zeile zweite zeile dritte zeile >>> s4='eins ' 'zwei' >>> s4 'eins zwei' >>> s5=('eins' ... 'zwei' ... 'drei') >>> s5 'einszweidrei' Neben dem bereits benutzten ``\n`` für Zeilenumbruch, sind andere wichtige Steuerzeichen innerhalb von Strings: ``\t`` (horizontaler Tab), ``\v`` (vertikaler Tab), ``\b`` (Backspace), ``\"`` (Doppeltes Hochkomma innerhalb eines String), ``\'`` (Einfaches Hochkomma innerhalb eines String). Methoden für Strings ^^^^^^^^^^^^^^^^^^^^^^ Zusätzlich zu den für alle sequenziellen Datentypen definierten Operationen, stellt Python String-spezifische Methoden bereit, von denen einige hier aufgeführt sind. Bei der Beschreibung der Methoden wird häufig allgemein der Begriff **Whitespace** benutzt. Damit können neben einem Leerzeichen auch Steuerzeichen für Zeilenumbruch, vertikaler oder horizontaler Tab gemeint sein. Für das **Aufspalten von Strings** in mehrere Bestandteile können u.a. folgende Methoden benutzt werden: .. method:: s.split(sep) trennt den String s an den Stellen, wo das Trennzeichen sep in s vorkommt. Wird der Methode kein Trennzeichen als Argument übergeben, dann wird s an allen Whitespaces getrennt. Die Methode gibt eine Liste von Strings zurück. .. method:: s.splitlines() Spaltet den String an den Zeilenumbruchstellen (``\n`` oder ``\r``) auf und gibt eine Liste mit der einzelnen Zeilen zurück. >>> s6="das ist das Haus vom\nNikolaus" >>> s6 'das ist das Haus vom\nNikolaus' >>> s6list=s6.split() >>> s6list ['das', 'ist', 'das', 'Haus', 'vom', 'Nikolaus'] >>> type(s6list) >>> s6="das-ist-das Haus vom\nNikolaus" >>> s6list2=s6.split('-') >>> s6list2 ['das', 'ist', 'das Haus vom\nNikolaus'] >>> s7="das ist \ndas Haus \nvom Nikolaus" >>> print s7 das ist das Haus vom Nikolaus >>> s7lines=s7.splitlines() >>> s7lines ['das ist ', 'das Haus ', 'vom Nikolaus'] **Suchen in Strings** In den folgenden Methodendefinitionen sind die Parameter ``start,end`` jeweils optional und legen Start- und Endposition des Intervalls fest, innerhalb dessen gesucht werden soll. Falls der Parameter nicht angegeben wird, wird im gesamten String gesucht. .. method:: s.find(x,start,end) liefert den Index des ersten Vorkommens von x im String s .. method:: s.rfind(x,start,end):: liefert den Index des letzten Vorkommens von x im String s Beispiele: >>> text='Es war was war und es kommt was kommt' >>> text.find('was') 7 >>> text.find('w',9,15) 11 >>> text.rfind('was') 28 **Ersetzen von Teilstrings / Entfernen von Zeichen** .. method:: s.replace(old,new):: ersetzt alle Vorkommen von ``old`` durch ``new`` .. method:: s.lower():: ersetzt alle Grossbuchstaben in s durch Kleinbuchstaben .. method:: s.upper():: ersetzt alle Kleinbuchstaben in s durch Grossbuchstaben .. method:: s.strip([char]):: entfernt die in ``[char]`` definierten Zeichen am linken und rechten Rand von s Beispiele: >>> text='Es war was war und es kommt was kommt' text.replace('war','wird') 'Es wird was wird und es kommt was kommt' >>> text.lower() 'es war was war und es kommt was kommt' >>> text.upper() 'ES WAR WAS WAR UND ES KOMMT WAS KOMMT' >>> t=' Das ist der gewünschte Text ' >>> t.strip('') ' Das ist der gewünschte Text ' Formatierung von Strings ^^^^^^^^^^^^^^^^^^^^^^^^^^ In Python ist für Strings der Formatierungsoperator ``%`` definiert. Dieser Operator erwartet zwei Operanden: Als ersten einen String, der die Formatierung beschreibt und als zweiten eine Sequenz, in der die Werte gespeichert sind, die formatiert ausgegeben werden sollen. Beispiele: >>> x1=3.2 >>> x2=4.678 >>> "Punktkoordinaten sind x1 = %5.1f, x2 = %5.1f" % (x1,x2) 'Punktkoordinaten sind x1 = 3.2, x2 = 4.7' >>> print "Punktkoordinaten sind x1 = %5.1f, x2 = %5.1f" % (x1,x2) Punktkoordinaten sind x1 = 3.2, x2 = 4.7 Im Beispiel definert ``%5.1f`` den Ausgabedatentyp, nämlich eine Gleitkommazahl mit 5 Vor- und einer Nachkommastelle. Für ganze Zahlen ist der Ausgabedatentyp ``%d``. .. _kapDict: Dictionaries ============== Mit Dictionarys (Python-Typ ``dict``) wird eine Zuordnung zwischen Objektpaaren hergestellt. Ein Dictionary kann beliebig viele Schlüssel/Wert - Paare (Key/Value - Pairs) aufnehmen. Im Gegensatz zu den Listen müssen die Keys nicht ganze Zahlen, sondern dürfen beliebige Objekte sein. Das Anlegen eines Dictionary und der Zugriff auf alle/einzelne Keys und Values kann folgendem Beispiel entnommen werden: >>> TrainElement={"feature" : (1.0,True,'kalt',2), "class" : 1, "partition" : 4} >>> print TrainElement {'partition': 4, 'feature': (1.0, True, 'kalt', 2), 'class': 1} >>> TrainElement.keys() ['partition', 'feature', 'class'] >>> TrainElement.values() [4, (1.0, True, 'kalt', 2), 1] >>> TrainElement['partition'] 4 >>> TrainElement['feature'] (1.0, True, 'kalt', 2) >>> TrainElement['feature'][2] 'kalt' Dictionaries sind iterierbare Objekte, d.h. sie können in einer for-Schleife durchlaufen werden. Dabei werden jedoch nur die Schlüsselelemente besucht: >>> for a in TrainElement: ... print a partition feature class Die Länge eines Dictionaries d, also die Anzahl der in d angelegten Schlüssel/Wert Paare, kann über ``len(d)`` abgefragt werden. Mit ``del d[k]`` wird das Element mit Schlüssel k gelöscht, mit ``k in d`` kann geprüft werden, ob sich der Schlüssel k in d befindet. Methoden die für jedes Dictionary d aufgerufen werden können sind: .. method:: d.clear():: löscht den Inhalt des Dictionaries .. method:: d.copy():: erzeugt eine Kopie von d. Die Werte des neuen Dictionary bleiben Referenzen auf die selben Objekte. Es handelt sich also um eine **flache Kopie** .. method:: d.items():: erzeugt eine Liste, die alle Schlüssel/Wert Paare von d als Tupel enthält .. method:: d.keys():: liefert Liste mit allen in d definierten Schlüssel .. method:: d.values():: liefert Liste mit allen in d definierten Werten .. method:: d.get(k,x):: liefert den Wert zu Schlüssel k falls dieser existiert, sonst x .. method:: d.setdefault(k,x):: setzt d[k]=x, wenn der Schlüssel k in d noch nicht vorhanden ist, ansonsten liefert es den Wert von k. .. method:: d.iteritems():: damit können in einer for-Schleife alle Schlüssel/Wert-Paare durchlaufen werden .. method:: d.iterkeys():: damit können in einer for-Schleife alle Schlüssel durchlaufen werden .. method:: d.itervalues():: damit können in einer for-Schleife alle Werte durchlaufen werden Beispiele hierzu sind: >>> for a in TrainElement.iteritems(): ... print a ... ('partition', 4) ('feature', (1.0, True, 'kalt', 2)) ('class', 1) >>> TrainElement.get('class',0) 1 >>> TrainElement.setdefault('class',0) 1 >>> TrainElement.setdefault('neu','element') 'element' >>> TrainElement {'neu': 'element', 'partition': 4, 'feature': (1.0, True, 'kalt', 2), 'class': 1} >>> del TrainElement['neu'] >>> TrainElement {'partition': 4, 'feature': (1.0, True, 'kalt', 2), 'class': 1} Mengen ======== Eine Menge ist ein ungeordneter Zusammenschluss von Elementen, wobei jedes Element nur einmal vorkommen kann. In Python gibt es für mutable Mengen den Typ ``set``, für immutable Mengen den Typ ``frozenset``. In dieser Einführung wird nur das ``set`` behandelt. Die Elemente einer Menge dürfen unterschiedlichen Typs sein. Eine leere Menge wird mit >>> m=set() angelegt. Alternativ kann dem Konstruktor beim Anlegen eines neuen Mengenobjektes schon ein iterierbares Objekt x (z.B. eine Liste, ein String oder ein Dictionary) übergeben werden. >>> m=set(x) Ist x ein Dictionary, dann enthält die angelegte Menge nur die Schlüssel von x. In der Textanalyse müssen häufig für Texte die in diesen vorkommenden Worte (Bag of Words) ermittelt werden. Dies lässt sich wie folgt bewerkstelligen: >>> text='Es war was war und es kommt was kommt' >>> textlist=text.split() >>> textlist ['Es', 'war', 'was', 'war', 'und', 'es', 'kommt', 'was', 'kommt'] >>> bagOfWords=set(textlist) >>> bagOfWords set(['und', 'es', 'kommt', 'was', 'war', 'Es']) Ist m ein Objekt vom Typ ``set`` oder ``frozenset``, dann können auf m folgende Operationen ausgeführt werden: * ``len(m)`` liefert die Anzahl der Elemente in m * ``x in m`` ist True, wenn x in m enthalten ist * ``m<=t`` ist True, wenn m eine Teilmenge von t ist * ``m>> text='Es war was war und es kommt was kommt' >>> textlist=text.split() >>> häufig=[x for x in textlist if textlist.count(x)>=2] >>> häufig ['war', 'was', 'war', 'kommt', 'was', 'kommt'] >>> einmal=set(textlist)-set(häufig) >>> einmal set(['und', 'Es', 'es']) Auf die Elemente einer Menge kann nicht direkt über einen Index zugegriffen werden. Hierfür muss die Menge ``m`` wieder in eine Liste ``l`` mit ``l=sorted(m)`` transformiert werden.