|
|
Was nicht so geht, wie erwartet ... |
|---|
Die Python - Dokumentation wächst und wächst. Immer mehr Module kommen in der Standardausstattung hinzu. Immer mehr Funktionen werden implementiert. Man kann sich kaum vorstellen, dass Python noch besser wird, als es schon ist, aber es geht tatsächlich! Und es wächst weiter.
Da nimmt es nicht wunder, dass auch mal etwas nicht so geht, wie erwartet. Oft ist es ein Veständnisproblem, weil die Funktion irgendeiner Sache nicht so gemeint war, wie der unbedarfte Programmierer es vielleicht aufgefasst hat. Aber es gibt auch andere Sachen, die wirklich nicht so gehen, wie beschrieben. Es sind oft auch nicht die lebensnotwendigen Dinge, sondern selten benötigte Funktionen. Möglicherweise liegt es auch an den rasch aufeinanderfolgenden Versionen von Python, den in dichter Folge einschlagenden neuen Ideen ...
Die hier nachfolgend beschrieben Einzelbeispiele will ich hier zur Diskussion stellen. Ich fange erstmal mit wenigen Beispielen an. Immer wenn mir wieder was auffällt, füge ich das dann hinzu. Sollte ich mich irgendwie irren, weil ich etwas nicht beachtet oder falsch interpretiert habe, bin ich für jede Aufklärung dankbar. Schließlich geht es um meine Lieblingsprogrammiersprache :-).
Fall 1:
Hier geht es um die Standardein- und ausgabe. In der Referenz zur Standardbibliothek (nachzulesen in der deutschen Ausgabe von M&T Seite 93) wird eine Beispielfunktion abgedruckt, die praktisch dasselbe macht, wie die Funktion raw_input(). Sie lautet so:
import sys
def getstring():
text = ""
while 1:
c = sys.stdin.read(1)
text = text + c
if c == '\n':
break
return text
Sie ist ein Beispiel dafür, wie man byteweise Zeichen einlesen kann. Wenn man sie so im Ganzen ausprobiert, geht es auch scheinbar, denn der gesamte String wird brav zurückgegeben. Sie erweckt aber den Eindruck, dass mit read(1) die Zeichen einzeln aus dem Tastaturpuffer genommen werden. Als ich diese Funktion vorfand, freute ich mich riesig, wollte ich doch mit einfachen Mitteln dem Nutzer ein Menue anbieten, dass durch Druck einer Zifferntaste die gewünschte Funktion gleich ausführt, ohne auf <Enter> zu warten. Denkste!! Es ging nicht. Als ich nach dem read(1) - Befehl dann mal ein print c einfügte, sah ich die Bescherung. Der Tastaturpuffer sammelt alle Tastenanschläge und läßt sie dann im Block nach <Enter> auf unser armes Python los! Na unter diesen Bedingungen nützt mir das byteweise Auslesen natürlich nichts! Es wäre ja schön gewesen, weil es plattformunabhängig geblieben wäre. Nun bleibt wieder nur "curses unter Linux" und "WConio unter Windows" anzuwenden.
Fall 2:
In der Zusatzdokumentation für curses (zu finden bei www.python.org), werden vordefinierte Konstante für Sondertasten bereitgehalten. Diese Werte werden aber bei Betätigung dieser Tasten nicht angeboten, sondern es kommen dafür Einzelbytes, und die sind für verschiedene Python - Versionen auch noch unterschiedlich! Im abgdruckten Beispiel wird aber locker die Eingabe mit getch() eingesetzt, die nun wirklich keine Integerwerte bringt. Alles kein Problem, läßt sich alles programmiertechnisch lösen. Aber die Doku stimmt da irgendwie nicht.
Fall 3:
Diesmal geht es mal nicht
um die Dokumentation, die ist hier korrekt, aber die Überraschung
lauert wieder für den alten Pascalprogrammierer. Es ist doch wohl
(in anderen Programmiersprachen) immer so gewesen, dass (5 and 6) das
Resultat 4 zurückbringt, den der
bitweise Vergleich der beiden Integer zeigt, die beiden Zahlen haben
nur
das Bit 2 zugleich gesetzt. Die anderen Bits sind unterschiedlich.
Nicht so bei Python!
print 5 and 6
>>> 6
Ich weiß, es steht
doch
klar in den Büchern, dass hier jede Zahl ungleich 0 ein True ist
und
die Kommandozeile wird eben von links nach rechts abgearbeitet. Das
merkt
man, wenn man eingibt
print 6 and 5
>>> 5
Aber man schaut doch nur in die Bücher, wenn man anders nicht weiterkann, oder? Und ich mußte hier reinschauen, wo ich dann schnell fand, wie man es machen muss - natürlich einfach und elegant wie immer in Python:
print 5 & 6
>>> 4
Geben wir das
sicherheitshalber auch mal mit vertauschten Operanden ein:
print 6 & 5
>>> 4
Das Ergebnis wie erwartet.
Die Welt ist wieder in Ordnung.
Nun noch etwas mit Spaß. Geben wir doch mal ab Version 2.2 im Interpreter ein:
import this
eigentlich dürfte jetzt nichts passieren, weil es kein Modul mit diesem Namen gibt. Aber weit gefehlt, hier handelt es sich wohl um ein eingebautes Späßchen. Es kommen einige Druckzeilen auf dem Bildschirm, die bei näherer Betrachtung sich als sehr wahr erweisen.
Was aber nun, wenn es doch ein Modul mit diesem namen gibt, weil wir es selbst geschrieben haben? Nun probieren wir es aus und schreiben ein kleines this.py mit dem Inhalt
print 'Hallo'
Nach dem Befehl "import this" im Hauptprogramm kommt nun tatsächlich der Ausdruck "Hallo". Das heißt unser o.g. Osterei kommt nur, wenn kein anderes Modul mit diesem Namen existiert.
Fall 5:
# vorgegebene ganzzahlen eingeben
a = 1
def vorgabe(ende):
werte = []
for i in range(1, ende+1):
werte.append(i)
print i,
e = input('>> ')
if e in werte:
return e
else:
return 0
b = vorgabe(12)
if b:
print b
else:
print 'falsch'