LF6 1.1 Python

LF6 1.1 Python

Bild von https://commons.wikimedia.org/wiki/File:Python_molurus_molurus-Portrait.jpg

Allgemeines

Fragen zum Text oder zu Python: https://discord.gg/TsaqyAQ

Videos: https://www.youtube.com/watch?v=TCwIIs_vwzQ

Python-Programm ausführen

Wir möchten ein Pythonprogramm in der Konsole ausführen. Dazu erstellen wir zuerst ein Pythonprogramm (Natürlich könnt Ihr auch einen der vielen Online-Editoren wie https://www.tutorialspoint.com/execute_python_online.php verwenden).

Wir öffnen z.B. nano:

nano hallo.py

und geben ein:

print("Hallo Ferdinand-Braun-Schule")

Zum ausführen können wir eingeben:

python hallo.py

oder aber die Rechte zum ausführen setzen:

chmod u+x hallo.py

Wir müssen in dem Programm noch den Interpreter einstellen:

nano hallo.py

und folgende Zeile ganz oben einfügen:

#!/usr/bin/env python

Das Programm wird mit folgendem Befehl aufgerufen:

./hallo.py 

Variablen

Video: https://youtu.be/TCwIIs_vwzQ?list=PLe2-EUuYYx2dmSq4yQ-AjSbdhFWSceelv

Variablen sind Speicher für Werte wie Zahlen oder Zeichenketten. Wir ändern unser Programm hallo.py so ab, dass es Variablen verwendet:

#!/usr/bin/env python
gruss = "Hallo Ferdinand-Braun-Schule!"
print(gruss)

Aufgabe

Teste folgenden Code:

#!/usr/bin/env python
gruss = "Hallo 'Ferdinand-Braun-Schule!'"
print(gruss)
#!/usr/bin/env python
gruss = 'Hallo "Ferdinand-Braun-Schule!"'
print(gruss)

Zeichen werden immer in “ oder ‘ gesetzt im Gegensatz zu Zahlen:

#!/usr/bin/env python
gruss = "Hallo Ferdinand-Braun-Schule!"
wert = 72
print(gruss)
print(wert)

Namen von Variablen dürfen nicht mit einer Zahl beginnen.

Wert einlesen

Um mit dem Anwender eines Programms zu interagieren, gibt es die Möglichkeit Tastatureingaben in eine Variable einzulesen:

#!/usr/bin/env python
gruss = input("Schreibe einen Gruss: ")
print(gruss)

Zahlen

Python kann auch interaktiv ausgeführt werden. Einfach in die Konsole python eingen:

python
2+5

Ergebnis: 7

a = 2
b = 5
a+b

Ergebnis: 7

Den Wert einer Variable kann man sehen, indem der Name in der Konsole eingegeben wird.

a

Ergebnis: 2

Unterschied zu einem Programm:

nanao zahl.py
a = 2
b = 5
a+b

Das Programm speichern und ausführen.

Ergebnis: Keine Ausgabe!

Die letzt Zeile muss abgeändert werden:

print(a+b)

Ausgabe: 7

Für Zahlen gibt es zwei Variablentypen die meistens verwendet werden: int und float. Int sind natürliche Zahlen (also ohne Komma) und float sind Fließkommazahlen (also mit Komma). Beide Typen gab es bereits bei dem ersten Computer der Welt, der Z1 von Konrad Zuse!

python

a = 2
type(a)

Ergebnis: <class ‘int’>

python
a = 2.23
type(a)

Ergebnsi: <class ‘float’>

a = "2.23"

type(a)

Ergebnis: <class ‘str’>

str steht für Stringund bezeichnet eine Zeichenkette. Der Unterschied ist wichtig, da mit Strings nicht gerechnet werden kann:

python
a = "2"
b = 5
a+b

Ergebnis TypeError

Aber:

python
"2" + "5"

Ergebnis: 25

Strings werden durch das Pluszeichen verbunden!

Programm “alter”

Das Programm soll das Geburtsjahr ausrechnen nachdem das Alter eingegeben wurde. Bitte 2017 durch das aktuelle Jahr ersetzen.

nano alter.py
alter = input("Gebe bitte Dein Alter ein: ")
geburtsJahr = 2017 - alter
print(geburtsJahr)

Ergebnis: TypeError

2017 ist eine Zahl und der Inhalt der Variable alter ein String.

Lösung: Den Typ der Variable alter konvertieren (umwandeln):

geburtsJahr = 2017 - int(alter)

Es können auch Zahlen in einen String umgewandelt werden:

geburtsJahr = str(2017) - int(alter)

Ergebnis: TypeError

Auch eine Umwandlung in Fließkomma ist möglich:

geburtsJahr = 2017 - float(alter)

Ergebnis: Das Ergebnis wird als Fließkommazahl ausgegeben. Python wandelt automatisch den Variiablentyp von 2017 zu float! Damit wird das Ergenis ebenfalls eine Fließkommazahl.

Vergleiche dazu:

float(20)

Ergebnis: 20.0

Strings und Hilfe

Als String werden in Python Zeichen in Anführungsstriche bezeichnet. Es können sowohl “ als auch ‘ verwendet werden.

python
"FBS!"
'FBS!'

Beides sind Strings. Strings können in Vaiablen gespeichert werden:

python
c='FBS'
c

Es ist möglich, Zeichen in einem String zu ersetzen:

python
c='Hallo FBS!'
c.replace('Hallo', 'Salut')

Aufgabe

1.) Speichere das Ergebnis von c.replace(‘Hallo’, ‘Salut’) in einer neuen Variable ab.

2.) Versuche in dem String “Hallo FBS! Alles klar?” den Buchstaben ‘a’ durch ‘b’ zu ersetzen. Werden alle “a” ausgetauscht oder nur das erste “a”?

Hilfe

Die Übersicht der Befehle zur manipulation von Strings ist vielfältig. Mit dem Befehl

python
dir(c)

bekommt man einen ersten Überblick über die Möglichkeiten.

Ein Beispiel:

python
c.upper()

Um Hilfe zu einem Befehl zu bekommen, kann der help-Befehl verwendet werden:

python
help("".replace)

Es kann auch verwendet werden:

python
help(c.replace)

Parameter in der Hilfe in eckigen Klammern sind optional.

Aufgabe

Ersetze im String “Hallo FBS! Alles klar?” nur das erste ‘a’ durch ein ‘b’.

Indizierung von Zeichenketten

Strings ist ein komplexer Datentyp, der sich aus vielen Variablen zusammen setzt mit jeweils einem Zeichen (char). Daher ist es möglich, jedes Zeichen in einem String einzeln anzusprechen (Stichwort Array von Chars):

python
c="Hallo Welt!"
c[4]

Wir fangen immer bei 0 an zu zählen.

Aufgaben

1.) Schreibe einen Befehl, der das letzt Zeichen “!” ausgibt.

2.) Welche Ausgabe erfolgt bei c[-1] und c[-2]?

Um Zeichenketten zu extrahieren, können die Start und End-Position in die Eckige Klammer eingetragen werden. Wir möchten “Ha” extrahieren:

c="Hallo Welt!"
c[0:1]

Die Ausgabe ist “H”. Das liegt daran, dass beim auftrennen von Strings immer die Stelle des Schnitts angegeben wird also das Ergebnis immer ein Zeichen zu wenig hat.

c="Hallo Welt!"
c[0:2]

Aufgabe

Teste die Ausgabe von c[-4:-1]. Erhälst Du das erwartete Ergebniss?

Listen

Listen speichern mehrere Elemente in einer Variable, ähnlich einer Einkaufsliste die mehrere Eintragungen hat. Das Kennzeichen einer Liste sind die eckigen Klammern mit den Elementen:

c=["Ferdinand Braun", 1850, 1918,"Physiker"]

Jedes Element lässt sich einzeln ansprechen:

c[0]

Ausgabe:

‘Ferdinand Braun’

Jedes Element hat seinen eigenen Variablentyp:

type(c[0])
type(c[1])

Aufgabe

  1. Welches Ergebnis kommt bei c[:2] heraus?

  2. Welchen Variablentyp hat der Listen-Abschnitt?

  3. Schaue Dir die Verfügbaren Optinen von “list” mit dir an.

  4. Füge mit dem Befehl c.append() “Nobelpreistraeger” an das Ender der Liste an.

  5. Schaue Dir mit dem Befehl help(c.remove) den Befehl remove an.

  6. Entferne “Physiker” aus der Liste.

TUPELS

Tupels sind ähnlich zu Listen aber es ist kein schreibender Zugriff möglich. Wir definieren ein Tupel analog zu einer Liste:

t = ("Hallo", 1, 2.3)

Greifen lesend auf einzelne Elemente zu:

t[-1]

Ausgabe: 2.3

Aufagbe

Vergleich die möglichen Befehle auf die Objekte tupel und list. Was fällt Dir auf? Vergleiche bitte mit dem Befehl dir(list) bzw. dir(tuple).

Dictonary

Dictonary ordnen Begriff paarweise einander zu:

d = {"boy":"Junge", "girl":"Mädchen"}

Bei einem Dictonary wird unterschieden zwischen einem Schlüssel (Key) und Wert (value). In dem Beispiel sind die englischen Wörter die Schlüssel und die deutschen Wörter die Werte.

Wir greifen auf die Werte über die Schlüssel zu:

d["boy"]

Ausgabe: ‘Junge’

Die Abfrage ist nur in die Richtung Key -> Value möglich und nicht in die andere Richtung.

Deer Rückgabewert kann auch eine Liste sein:

d = {"boy":"Junge", "girl":"Mädchen", "eat":("frisst", "isst"), "have":("haben","bin","besitze")}

Ausgabe:

 d["have"]
 ('haben', 'bin', 'besitze')

Bei der Liste kann dann auch auf einzelne Elemente zugegriffen werden, wie wir es oben bereits bei den Listen gesehen haben:

 >>> d["have"][1]
'bin'

Aufgabe

Bitte fürhre diesen Test durch:

http://fachinformatiker-fulda.de/index.php/2017/09/18/quiz-python-1/ Du solltest 100% erreichen!

Funktionen

Funktionen werden eingesetzt um ein Programm zu strukturieren und/oder öfter benötigten Programmcode nur an einer Stelle vorzuhalten. Funktionen werden mit dem Wort def gefolgt vom Funktionnamen gekennzeichnet. Sie werden beim starten des Pythonprogramms erstbei aufruft über den Funktionsnamen ausgeführt. Wir verwenden viele in Python eingebaute Funktionen bereits wie z.B. print() oder input(). Wir programmieren als Beispiel einen Währungsumrechner. Der Umrechner soll Euro in die polnische Währung Zloty umrechnen. Wir benötigen dazu zwei Angaben: dem Umrechnungskurs und die Menge an Euros die umgerechnet werden soll. Momentan liegt der Umrechnungsfaktor bei 4,3: 1 Euro ist also 4,3 Zloty wert. Bitte überprüfe den Wert. Werte werden Funktionen mit Hilfe sogeannter Parameter übergeben, die in Klammern geschrieben werden. Mit dem Befehl return wird das Ergebnis der Funktion zurück gegeben an die aufrufende Stelle. Wenn wir das Programm ausführen werden wir keine Ausgabe erhalten, weil die Fuunktion nicht aufgerufen wird.

def waehrungsrechner(kurs, euro):
    zloty = euro*kurs
    return zloty

Wir ergänzen das Programm um einen Funktionsaufruf. Wir möchten 100 Euro umtauschen:

def waehrungsrechner(kurs, euro):
    zloty = euro*kurs
    return zloty
    
print(waehrungsrechner(4.3,100))    

Fehler

Fehler sind meschlich und nicht schlimm. Es kommt nur drauf an mit Ihnen sinnvoll umzugehen. Ferler werden auch Error oder Bug genannt. Die Bezeichnung Bug kommt daher, dass bei den Computern füher sich kleine Tiere zwischen den elektrischen Kontakten ihr Leben aushauchen konnten und so die Funktionsfähigkeit des Computers beeinträchtigten (siehe z.B. hier: https://de.wikipedia.org/wiki/Programmfehler#/media/File:H96566k.jpg oder auch https://de.wikipedia.org/wiki/Programmfehler)

In Python gibt es 3 Kategorien von Fehlern: Logische Fehler, Syntax-Fehler und Ausführungsfehler (Exception). Wir konzentrieren uns zuerst auf die Syntax-Fehler, die den größten Teil darstellen. Dazu ein Programm mit dem tollen Namen fehler.py:

print("1")
int(10)
int 9
print(2)
print "FBS"

Ausgabe:

Traceback (most recent call last):
  File "fehler.py", line 3
    int 9
        ^
SyntaxError: invalid syntax

Die zweite Zeile teilt uns den Namen der betroffenden Datei mit, in diesem Fall fehler.py.

Syntaxfehler

Der Fehler beruht darauf, dass int() eine Funktion ist und damit die Argumente in Klammer geschrieben werden. Wir korrigieren Die Zeile und führen das Programm erneut aus.

print("1") 
int(10) 
int(9) 
print(2) 
print "FBS" 

Wir treffen auf den nächsten Fehler (die Anzeige hier stammt von QPython unter Android):

File "/storage/emulated/0/qpython/.last_tmp.py", line 5 
print "FBS" 
          ^ SyntaxError: invalid syntax 

Wir sehen an der veränderten Zeilennummer, dass der vorhergehende Fehler behoben wurde. Print ist ebenfalls eine Funktion und muss daher in Klammern geschrieben werden. Bei der ausführung unter Anaconda wird direkt auf die fehlenden Klammern hingewiesen.

Wir korrigieren auch diesen Fehler:

print("1") 
int(10) 
int(9) 
print(2) 
print("FBS") 

und das Programm läuft fehlerlos durch:

1 
2 
FBS 

Wir bauen noch einen Fehler in das Programm ein:

print("1") 
int(10) 
int(9) 
print(2) 
print("FBS") 
a = [2,3,4) 

Das Programm erzeugt bei Ausführung einen Fehler:


File "/storage/emulated/0/qpython/.lasttmp.py", line 6 
a = [2,3,4) 
          ^ SyntaxError: invalid syntax 
1|u0a76@sofia3gr:/ $

Der Fehler ist leicht zu beheben:

print("1") 
int(10) 
int(9) 
print(2) 
print("FBS") 
a = [2,3,4] 

Und das Programm läuft problemlos durch.

Wir ändern das Programm nochmals ab:

print("1") 
a = 1 
b = "2" 
print(int(2) 
print("FBS") 
print(a+b) 

Und wir bekommen eine Fehlermeldung:

File "/storage/emulated/0/qpython/.lasttmp.py", line 5 
print("FBS") 
^ SyntaxError: invalid syntax 1|
u0a76@sofia3gr:/ $ 

In der Zeile 5 ist aber kein Fehler. Der Fehler ist in Zeile 4. Dort wurde vergessen, eine Klammer zu schließen. Python fällt das aber erst in der nächsten Zeile auf, weil für den Interpreter völlig überraschend ein weiterer Befehl kommt, der nicht in den Kontext passt.

print("1") 
a = 1 
b = "2" 
print(int(2)) 
print("FBS") 
print(a+b) 

Syntaxfehler gehören meist zu den einfach zu behebenen Fehlern. Meistens ist der Fehler an der angegebenen Stelle. Selten kann es vorkommen, dass der Fehler eine Zeile vorher entsteht.

Python überprüft vor der Ausführung den Quellcode auf Syntaxfehler, erst danach wird das Programm ausgeführt und es kann zu Ausführungsfehlern kommen.

Ausführungsfehler

Wir führen das Programm von oben aus und treffen bekommen eine weitere Fehlermeldung:

1 
2 
FBS 
Traceback (most recent call last): 
File "/storage/emulated/0/qpython/.lasttmp.py", line 6, in <module> 
print(a+b) 
 TypeError: unsupported operand type(s) for +: 'int' and 'str' 1|
 u0a76@sofia3gr:/ $ 

Wir sehen an der Ausgabe, dass das Programm bereits zum Teil abgearbeitet worden ist. Auch der Hinweis auf einen Syntaxfehlers fehlt. Beides Hinweise auf einen Ausführungsfehler. Das bedeutet, dass die Syntax eingehalten worden ist und ein Problem der Variablenwerte vorliegt. Die Meldung gibt uns auch den entsprechenden Hinweis.

Wir korrigieren das Programm:

print("1") 
a = 1 
b = 2 
print(int(2)) 
print("FBS") 
print(a+b) 

Es gibt noch viele andere Ausführungsfehler neben dem Ty-Fehler. Ein weiterer häufiger Fehler ist der Bezeichner-Fehler (name error):


print("1") 
a = 1 
b = 2 
print(int(2)) 
print("FBS") 
print(a+c) 

Bei der Ausführung bekommen wir den Hinweis:


1 
2 
FBS 
Traceback (most recent call last): 
File "/storage/emulated/0/qpython/.lasttmp.py", line 6, in <module> 
print(a+c) 
NameError: name 'c' is not defined 1|
u0a76@sofia3gr:/ $ 

Python kann zum Zeitpunkt der Ausführung die Variable c nicht ansprechen. Es kann durchaus sein, dass die Variable später existiert oder in einem lokalen Kontext. Zum Zeitpunkt der Ausführung der Zeile 6 existiert die Variable aber nicht!

Ein weiter beliebter Ausführungsfehler ist der einer nicht definierten mathematischen Berechnung.

print("1") 
a = 1 
c = 0 
print(int(2)) 
print("FBS") 
print(a/c) 

Es kommt zu folgender Fehlermeldung:

1 
2 
FBS 
Traceback (most recent call last): 
File "/storage/emulated/0/qpython/.lasttmp.py", line 6, in <module> 
print(a/c) 
ZeroDivisionError: division by zero 1|
u0a76@sofia3gr:/ $ 

Zahlenraten

Wir schreiben unser erstes eigenes Programm: Zahlenraten

Der Computer denkt sich eine Zahl zwischen 0 und 100 aus. Der Mensch soll die Zahl erraten und hat die Möglichkeit die Zahl mit 6 Versuchen zu erraten. Der Computer kennt drei Reaktionen auf eine Eingabe: “Meine Zahl ist größer!”, “Meine Zahl ist kleiner!” und “Gewonnen!”. Durch geschicktes raten sollte es möglich sein, jede Zahl mit 6 Versuchen zu erraten.

Wir verwednen dafür die Testgetriebene Entwicklung (TDD, vgl. https://de.wikipedia.org/wiki/Testgetriebene_Entwicklung) und legen 2 Dateien an mit den Namen test.py und zahlenraten.py

Die Datei test.py führt sogenannte Unity Tests aus auf die Dateie zahlenraten und gibt uns Rückmeldung ob die Funktionen der Datei ordnungsgemäß arbeiten. Später können die Unity Test durch automatisierte Verfahren automatisch nach Codeänderungen ausgeführt werden und verhindern so, dass sich durch nachträglich Veränderungen am Quellcode Fehler eingeschlichen haben.

test.py:

import unittest
from zahlenraten import ueberpruefung
class zahlenraten_ueberpruefung(unittest.TestCase):
    pass
    
if __name__ == "__main__": 
    unittest.main()

Wir importieren zuerst die Klasse Unittest, die die entasprechende Befehle für einen Test bereitstellt und wir importieren in der zweiten Zeile den zu testenden Programmcode.In der dritten Zeile erstellen wir eine Klasse (was immer das ist), die den Programmcode dann testet.

Die Datei zahlenraten.py:

def ueberpruefung(eingabe, testwert):
    pass

def zufallszahl():
    pass

zahl = zufallszahl()

eingabewert = input("Bitte eine Zahl eingeben: ")
ueberpruefung(eingabewert)    

    
print("Das Spiel ist zu Ende")    

Wir definieren eine Funktion ueberpruefung mit 2 Parametern: eingabe und testwert. Die Funktion macht noch überhaupt nichts, pass bedeutet: “nichts machen”. Ebenso bei der Funktion zufallszahl. Die erste Zeile, die beim start des Programms ausgeführt wird ist “zahl=zufallszahl” in der die Funtkion Zufallszahl aufgerufen wird und das Ergebnis nach zahl gespeichert wird.

Die nächste Zeile fordert den Benutzer zu einer Eingabe auf und speichert diese in die Variable eingabewert ab. Danach wird die Funktion ueberpruefung aufgerufen, die später die Ausgabe “größer”, “kleiner” oder “treffer” ausgeben soll.

Die letzte Zeile zeigt uns an, dass das Programm bis zum Ende abgearbeitet worden ist.

Wir definieren jetz einen Test um in der Funktion ueberpreuefung negative Zahlen abzufangen:

import unittest
from zahlenraten import ueberpruefung
class zahlenraten_ueberpruefung(unittest.TestCase):
    
    def testCalculation(self):
        """Wird eine negative Zahl abgelehnt?"""
        for index in range(-1, -10, -1):
            self.assertFalse(ueberpruefung(index))
            
if __name__ == "__main__": 
    unittest.main()

Der Test schlägt natürlich Fehl, da wir noch nichts programmiert haben:

Bitte eine Zahl eingeben: 1
Das Spiel ist zu Ende
.
----------------------------------------------------------------------
Ran 1 test in 0.002s

OK
Traceback (most recent call last):
  File "/home/pi/python/test.py", line 11, in <module>
    unittest.main()
  File "/usr/lib/python3.5/unittest/main.py", line 94, in __init__
    self.runTests()
  File "/usr/lib/python3.5/unittest/main.py", line 257, in runTests
    sys.exit(not self.result.wasSuccessful())
SystemExit: False

Was ist der einfachste Weg, den Test zu erfüllen? Genau, wir geben ein False zurück:

def ueberpruefung(eingabe, testwert):
    return False

def zufallszahl():
    pass

zahl = zufallszahl()

eingabewert = input("Bitte eine Zahl eingeben: ")
ueberpruefung(eingabewert, zahl)    

    
print("Das Spiel ist zu Ende") 

Und wir bekommen einen positiven Testdurchlauf:

>>> %Run test.py
Bitte eine Zahl eingeben: 1
Das Spiel ist zu Ende
.
----------------------------------------------------------------------
Ran 1 test in 0.001s

OK

Manche Editoren geben leider auch einen Trace zurück, wenn kein Fehler aufgetreten ist. Dies können wir unterbinden, indem wir die letzten beiden Zeilen durch diesen Code ersetzen:

if __name__ == "__main__": 
    try:
        unittest.main()
    except SystemExit as inst:
        if inst.args[0] is True: 
            raise

Damit wird nur im Fehlerfalle ein Trace ausgegeben. Dieses verhalten zeigt das Programm auch beid er Ausführung innerhalb der Konsole.

Wir testen jetzt, ob Zahlen größer 100 abgelehnt werden. Das schöne ist, dass wir hier ebenfalls ein False als Rückgabewert erwarten.

import unittest
from zahlenraten import ueberpruefung
class zahlenraten_ueberpruefung(unittest.TestCase):
    
    def testCalculation(self):
        """Wird eine negative Zahl abgelehnt?"""
        for index in range(-1, -10, -1):
            self.assertFalse(ueberpruefung(index))
        """Wird eine Zahl größer 100 abgelehnt"""
        self.assertFalse(ueberpruefung(101))
        
# Diese komplizierte Struktur ermöglicht es auch bei IDEs, die immer einen Trece ausgeben, diesen zu unterbinden, wenn kein Fehler aufgetreten ist.        
if __name__ == "__main__": 
    try:
        unittest.main()
    except SystemExit as inst:
        if inst.args[0] is True: 
            raise

Und wir bekommen wieder einen positiven Durchlauf:

>>> %Run test.py
Bitte eine Zahl eingeben: 1
Das Spiel ist zu Ende
.
----------------------------------------------------------------------
Ran 1 test in 0.001s

OK

Jetzt überprüfen wir die Zahlen zwischen 0 und 100, die ein True zurückgeben sollen:

import unittest
from zahlenraten import ueberpruefung
class zahlenraten_ueberpruefung(unittest.TestCase):
    
    def testCalculation(self):
        for index in range(-1, -10, -1):
            self.assertFalse(ueberpruefung(-10))
        print("Negative Zahlen")

        self.assertFalse(ueberpruefung(101))
        print("Zahlen größer 100")
    
        for index in range(1, 100, 1):
            self.assertTrue(ueberpruefung(1))
        print("Zahlen zwischen 0 und 100")
# Diese komplizierte Struktur ermöglicht es auch bei IDEs, die immer einen Trece ausgeben, diesen zu unterbinden, wenn kein Fehler aufgetreten ist.        
if __name__ == "__main__": 
    try:
        unittest.main()
    except SystemExit as inst:
        if inst.args[0] is True: 
            raise

Jetzt müsste eigentlich ein Fehler gemeldet werden und er wird auch angezeigt:

import unittest
from zahlenraten import ueberpruefung
class zahlenraten_ueberpruefung(unittest.TestCase):
    
    def testCalculation(self):
        for index in range(-1, -10, -1):
            self.assertFalse(ueberpruefung(index))
        print("Negative Zahlen")

        self.assertFalse(ueberpruefung(101))
        print("Zahlen größer 100")
    
        for index in range(1, 100, 1):
            self.assertTrue(ueberpruefung(index))
        print("Zahlen zwischen 0 und 100")
# Diese komplizierte Struktur ermöglicht es auch bei IDEs, die immer einen Trece ausgeben, diesen zu unterbinden, wenn kein Fehler aufgetreten ist.        
if __name__ == "__main__": 
    try:
        unittest.main()
    except SystemExit as inst:
        if inst.args[0] is True: 
            raise

Und hier der Fehler:

Bitte eine Zahl eingeben: 1
Das Spiel ist zu Ende
Negative Zahlen
Zahlen größer 100
F
======================================================================
FAIL: testCalculation (__main__.zahlenraten_ueberpruefung)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/pi/python/test.py", line 14, in testCalculation
    self.assertTrue(ueberpruefung(index))
AssertionError: False is not true

----------------------------------------------------------------------
Ran 1 test in 0.003s

FAILED (failures=1)
Traceback (most recent call last):
  File "/home/pi/python/test.py", line 19, in <module>
    unittest.main()
  File "/usr/lib/python3.5/unittest/main.py", line 94, in __init__
    self.runTests()
  File "/usr/lib/python3.5/unittest/main.py", line 257, in runTests
    sys.exit(not self.result.wasSuccessful())
SystemExit: True

Wir passen unser Programm entsprechend an:

def ueberpruefung(eingabe):
    if 0<= eingabe <=100:
        return True
    else:
        return False

def zufallszahl():
    pass

zahl = zufallszahl()

eingabewert = input("Bitte eine Zahl eingeben: ")
ueberpruefung(eingabewert)    

    
print("Das Spiel ist zu Ende")    

Wir bekommen nun eine Fehlermeldung:

Bitte eine Zahl eingeben: 1
Traceback (most recent call last):
  File "/home/pi/python/test.py", line 2, in <module>
    from zahlenraten import ueberpruefung
  File "/home/pi/python/zahlenraten.py", line 13, in <module>
    ueberpruefung(eingabewert)
  File "/home/pi/python/zahlenraten.py", line 2, in ueberpruefung
    if 0<= eingabe <=100:
TypeError: unorderable types: int() <= str()

Der Fehler leigt daran, das der befehl input immer einen String einliest. Den Fehler verbessern wir jetzt indem wir den Typ umwandeln:

def ueberpruefung(eingabe):
    if 0<= eingabe <=100:
        return True
    else:
        return False

def zufallszahl():
    pass

zahl = zufallszahl()

eingabewert = input("Bitte eine Zahl eingeben: ")
eingabewert = int(eingabewert)
ueberpruefung(eingabewert)    

    
print("Das Spiel ist zu Ende")    

Wir geben beim start des Programms einen Buchstaben ein und das Programm stürzt ab:

>>> %Run zahlenraten.py
Bitte eine Zahl eingeben: m
Traceback (most recent call last):
  File "/home/pi/python/zahlenraten.py", line 13, in <module>
    eingabewert = int(eingabewert)
ValueError: invalid literal for int() with base 10: 'm'

Wir führen die Typumwandlung in der Funktion überprüfen aus um den Fehler abzufangen. Dafür schreiben wir erst eine Testfunktion:

import unittest
from zahlenraten import ueberpruefung
class zahlenraten_ueberpruefung(unittest.TestCase):
    
    def testCalculation(self):
        for index in range(-1, -10, -1):
            self.assertFalse(ueberpruefung(index))

        self.assertFalse(ueberpruefung(101))
    
        for index in range(1, 100, 1):
            self.assertTrue(ueberpruefung(index))
        
        self.assertFalse(ueberpruefung("m"))
# Diese komplizierte Struktur ermöglicht es auch bei IDEs, die immer einen Trece ausgeben, diesen zu unterbinden, wenn kein Fehler aufgetreten ist.        
if __name__ == "__main__": 
    try:
        unittest.main()
    except SystemExit as inst:
        if inst.args[0] is True: 
            raise

Jetzt passen wir das Programm an, damit kein Fehler mehr auftritt:

def ueberpruefung(eingabe):
    try:
        eingabe = int(eingabe)
        if 0<= eingabe <=100:
            return True
        else:
            return False
    except ValueError:
        return False
    

def zufallszahl():
    pass

zahl = zufallszahl()

eingabewert = input("Bitte eine Zahl eingeben: ")
ueberpruefung(eingabewert)    

    
print("Das Spiel ist zu Ende")    

Schreibe eine Testfunktion, dass die Funktion zufallszahl nur Zahlen zwischen 0 und 100 liefert. Schreibe dann die Funktion zufallszahl.

Schreibe eine Funktion auswertung, die feststellt ob die eingegebene Zahl größer, kleiner oder gleich der Zufallszahl ist. Die Funktion wird mit 2 Parametern aufgerufen: eingegebene Zahl und die Zufallszahl. Selbstverständlich schreiben wir zuerst einen test.

Wir setzen die Zeile mit dem Befehl input in eine geeignete Schleife, so dass diese maximal 10 mal durchlaufen wird. Wurde die Zahl erraten, wird die Schleife mit einer entsprechenden Meldung beendet. Wird die maximale Zahl überschritten, kommt ebenfalls eine entsprechende Meldung.

Schleifen

Es gibt einmal die “for-Schleife” und auf der anderen Seite die “while-Schleife”. Die “for-schleife” ist dafür gedacht, bestimmte Befehle n mal auszuführen. N ist bei Eintritt in die Schleife ein fester Wert. Die “While-Schleife” wird verwendet um einen Code-Block solange auszuführen, solange eine Bedingung wahr ist.

For-Schleife