Weitere Tips, Ratschläge und Hinweise

Zurück zur Hauptseite

 


zur Kochbuchseite

zum Python - Lexikon


Beim schrittweisen Kennenlernen von Python bin ich immer wieder überrascht worden. Das waren teilweise angenehme Überraschungen (es ging irgendwas besser, als ich erwartet hatte), aber es gab auch vorerst unverständliche Dinge, die teilweise erst nach einiger Arbeit eingegrenzt werden konnten. Die letzteren sollen hier als helfender Ratschlag vermerkt werden. 


Wenn man den doc-String (der mit "''' eingeschlossen ist)  mit idle ansehen will, sollte man

            print modulname.__doc__

eingeben (nicht ohne print, sonst geht auf dem Screen alles durcheinander!).


Die Funktionen in dem Modul msvcrt (hier ist es mir mit der Funktion "kbhit" aufgefallen), die für den Pythoneinsatz unter Windows vorgesehen sind, funktionieren anscheinend nicht unter der idle, sondern nur im Kommandofenster!


Durch das das print-scolling steht der Kursor auf der vollgeschriebenen Seite immer unten und schiebt bei weiteren Ausgaben alles nach oben. Will man den Bildschirm mal wieder aufräumen, hilft:

            import os
            a = os.system('clear')
            # auf Linuxsystemen. Bei Windows stattdessen das Komando 'cls'

  a fängt den Rückgabewert ab, der sonst auf dem Bildschirm erscheint


range() geht auch mit einem einzigen Argument. Dann geht es jeweils bei 0 los. Ist das Argument 1, dann entsteht [0]. Ist das Argument kleiner als 1, entsteht []


Es gibt Schwierigkeiten, wenn man ein Modulname einen Bindestrich enthält.  Anscheinend wird das dann beim Aufruf des Moduls so interpretiert, als wenn Parameter folgen würden.


Folgender Hinweis gilt, wenn man aus bestimmten Gründen gezwungen ist, mit einer älteren Version von Python zu arbeiten und dabei auf die Idle zurückgreift:

Wenn man dann ein Python-Modul, das unter Windows entwickelt wurde, auch unter Linux einsetzten oder weiterentwickeln will, müssen vorher die Windows/DOS - typischen Wagenrückläufe \r entfernt werden. Dies ist mir zumindest passiert, als ich ein solches Modul unter Idle mit Linux starten wollte. Promt kam eine Fehlermeldung und die \r waren im Editor auch sichtbar.



Ein Tupel ist unveränderlich, d.h. ich kann seine Elemente nicht durch Zuweisung ändern. So bringt z. B.

t = (100, 200)
t[1] = 3

sofort eine Fehlermeldung. Aber Achtung! Enthalten die Elemente des Tupels selbst Veränderliche, dann geht es trotzdem!
z. B.

L1 = ['europa', 'asien']
L2 = ['amerika']
t = (L1, L2)

dann geht es, mit t[1][0] = 300 zuzuweisen. Allerdings ist das Ergebnis nicht etwa t = (L1, 300) sondern 

t = (['europa', 'asien'], [300])


Eine ähnliche Überraschung wartet auf uns bei der Parameterbehandlung durch Funktionen. Die Parameterübergabe erfolgt "call by reference", d.h. die Funktion erhält eigentlich einen Zeiger (Adresse) auf die übergebene Variable. So steht es jedenfalls in den Pythonbüchern, die etwas über die Interna von Python verraten. Als alter Pascalanhänger ist man geneigt, sofort die klassischen Schulbeispiele dazu auszuprobieren, die man damals gezeigt bekam um den Unterschied der Variablenübergabe direkt oder mit "var" gegenüberzustellen. Probieren wir doch einfach selbst:

1. Einfaches Objekt

a = 100

def set(x):
     x = 2

set(a)
print a

bringt nach dem Start:

>>> 100

Nanu, stimmt da etwas nicht? Wir hatten doch jetzt erwartet, dass der Wert von a sich auf 2 geändert hätte. Erfolgt die Variablenübergabe etwa doch auf die Weise, dass eine Kopie der Variablen angelegt wird, die dann zwar intern verändert werden kann aber nach draußen keine Veränderung bewirkt? Das wäre nämlich eine Parameterübergabe call by value und die Lehrbücher hätten sich alle geirrt !!

Probieren wir sicherheitshalber etwas ausführlicher:


2. ein anderer Versuch mit einfachen Objekten

def tausch(x, y):
    x, y = y, x
    return x, y

a = 100
b = 200

print a, b

a, b = tausch(a, b)

print a, b

hier kommt folgende Ausgabe:

>>> 100, 200
>>> 200, 100

aha, also geht es doch! Die neuen Werte müssen natürlich auch nach der Behandlung in der Funktion nach draußen transportiert werden. Dafür funktioniert aber die Vorgehensweise im Versuch 1 bei veränderlichen Objekten:

3. Veränderliches Objekt

a = [1, 2, 3]

def set(x):
     x[0] = 2

set(a)
print a

bringt nach dem Start:

>>> [2, 2, 3]

Die Funktion hat hier also auch ohne besondere Maßnahmen in die aufrufende Umgebung gegriffen.


Slicing geht auch mit Strings, die in Listen geordnet sind. So ist z.B.

>>> L = ['Hallo', 'Berlin', 'Deutschland']

>>> L[1][0:-1]

 'Berli'

Das läßt sich z.B. anwenden, wenn man aus einem File mit readlines alle Textzeilen in eine Liste eingelesen hat, und sich danach ärgert, dass alle Zeilen mit einem Zeilenendezeichen versehen sind. Dann kann mit Slicing genau das letzte Byte beim Zugriff jeweils entfernt werden.


Bei der Division von Integerzahlen werden entstehende Dezimalstellen abgeschnitten. So bringt z.B.

>>> min = 59
>>> min/60
0

Noch überraschender wird es, bei negativen Zahlen:

  >>> -3/2
  -2

Hier wird auf die nächstgrößere Zahl (in negativer Richtung) hin gerundet!!

Möchter man gern, dass das Ergebnis genauer herauskommt, hilft ein kleiner Trick:

>>> min/60.0
0.98333333333333328

Da im Quotient nicht alle Zahlen Integer sind, kommt als Ergebnistyp float heraus. Man muß es nur wissen.


Typenvergleich

Mit der Funktion type() lässt sich feststellen, von welchem Typ eine Variable ist. Beispiel:

>>> print type('#')
<type 'string'>
>>>

Um nun eine Fallunterscheidung zwischen verschiedenen Typen zu machen, weil davon abhängt, wie ein Wert weiterverarbeitet wird (wir durchmustern z.B. ein Tupel, dessen Elemente ja sonst was sein können und nicht jede Operation geht auf jeden Typ anzuwenden) gibt man zum Vergleich natürlich nicht so ein Konstrukt ein, wie die type - Funktion liefert, sondern man nimmt einfach einen elemntaren vertreter seiner Klasse. Beispiel, wir wollen prüfen, ob a vom Typ integer ist:

if type(a) == type(1):
    print 'es ist so!'

oder wir vergleichen, wenns um Strings geht, mit type('') usw.