Listen und Tupels

Statt Werte in verschiedenen Variable a, b, c  einzeln abzuspeichern, stellt Python Listen und Tupels zur Verfügung, die als Behälter für beliebig viele Daten verwendet werden. Die Elemente einer Liste werden in eckigen Klammern zusammengefasst. In anderen Programmiersprachen verwendet man dazu oft Arrays. Im Gegensatz zu Arrays haben Listen keine feste, vordefinierte Länge, d.h. ihre Länge wird der Anzahl gespeicherter Elemente automatisch angepasst (dynamische Datenstruktur).

Tupels werden mit runden Klammern zusammengefast und werden oft für die Koordinaten verwendet.


Beispiel 1: Liste mit Farben

Die Liste colors enthält 6 Farben. Mit for c in colors: geht man die Liste durch, zeichnet mit jeder Farbe einen gefüllten Kreis und verschiebt die Turtle um 40 Schritte.

#Tu13.py

from gturtle import *

makeTurtle()

colors = ["red", "blue", "yellow", "green", "black", "cyan"]
for c in colors:
    setPenColor(c)
    dot(40)
    forward(40)
hideTurtle() 
Programmcode markieren (Ctrl+C kopieren, Ctrl+V einfügen)
 




Erklärungen zum Programmcode:

for c in colors : Die nachfolgende Anweisungen werden der Reihe nach für alle Elemente der Liste ausgeführt

 

Beispiel 2: Elemente hinzufügen und auf einzelne Elemente zugreifen

Mit dem Befehl append kann eine Liste mit weiteren Elementen erweitert werden.
colors.append("magenta") fügt eine weitere Farbe hinzu.
Mit print(colors) werden alle Elemente der Liste im Ausgabefenster angezeigt:

['red','blue','yellow','green','black','cyan','magenta']

Mit einem Index kann man auf die einzelnen Elemente der Liste zugreifen. Das erste Element hat den Index 0. colors[0] ist die Farbe red, colors[1] die Farbe blue usw.
Mit print(colors[2]) wird im Ausgabefenster yellow angezeigt.
Anzahl Elemente der Liste kann man mit len(colors) abfragen.

#Tu13a.py

from gturtle import *

makeTurtle()

colors = ["red", "blue", "yellow", "green", "black", "cyan"]
colors.append("magenta")
print(colors)
for c in colors:
    setPenColor(c)
    dot(40)
    forward(40)
hideTurtle() 

print(colors[2])
print(len(colors))
Programmcode markieren (Ctrl+C kopieren, Ctrl+V einfügen)
 


Erklärungen zum Programmcode:

colors.append("magenta") : fügt das Element "magenta am Ende der Liste colors hinzu
print(colors): Zeigt alle Elemente der Liste
print(colors[2]): Zeigt das Element mit dem Index 2 an, d.h. das dritte Element der Liste
len(colors): Gibt die Anzahl Elemente (die Länge) der Liste an
Weitere Befehle für den Umgang mit Liste sieht man unten auf dieser Website

 

Beispiel 3: Liste mit Punkt-Koordinaten (Tupels)

Die Liste house enthält die Koordinaten der Eckpunkte der neben stehenden Figur. Die Elemente der Liste sind Tupels (x, y). Im Programm geht man mit einer for-Schleife die Liste durch und verbindet die nacheinanderfolgende Punke.

Auf die Elemente eines Tupels kann man gleich zugreifen, wie auf Elemente einer Liste. p[0] liefert das erste Element (x-Koordinate), p[1] liefert die y- Koordinate.

#Tu13b.py

from gturtle import *

makeTurtle()

house = [(0, 60), (50, 110), (100, 60), (100, 0), (0, 0)]

for p in house:
    moveTo(p)
    
p = house[2]
print(p)
print(p[0])
print(p[1])
   
Programmcode markieren (Ctrl+C kopieren, Ctrl+V einfügen)
 




Erklärungen zum Programmcode:

(0, 60) : Tupel mit Koordinaten eines Punktes
house[2] : Das dritte Element der Liste house ist der Punkt p = (100, 60)
print(p[0]) :Zeigt das erste Element des Tupels p an (die x-Koordinate 100)
p[1] : Die y-Koordinate des Punktes p

 

Beispiel 4: Elemente der Liste dynamisch per Mausklick hinzufügen

Die Anzahl Elemente einer Liste kann während der Programmausführung verändert werden. Es ist sogar möglich eine ganze Liste dynamisch zu erzeugen. Die Liste points ist zu Beginn leer. Mit jedem Mausklick wird ein Punkt mit den Koordinaten des Mausklicks erzeugt und gezeichnet.
Der neu erzeugte Punkt wird danach unter Verwendung einer for-Schleife, die alle Elemente der Liste points durchgeht, mit allen vorhandenen Punkten verbunden. Anschliessend wird der Punkt zu Liste hinzugefügt und die aktuelle Liste mit print(points) im Ausgabefenster angezeigt.

#Tu13c.py

from gturtle import *

def onMousePressed(x, y):
    p = (x, y)
    setPos(p)
    dot(10)
    for q in points:
        setPos(p)            
        moveTo(q)  
    points.append(p)
    print(points)  
                
makeTurtle(mousePressed = onMousePressed)
hideTurtle()
points = []
Programmcode markieren (Ctrl+C kopieren, Ctrl+V einfügen)
 

Erklärungen zum Programmcode:

points= []: Erzeugt eine leere Liste
p = (x, y): Koordinaten x, y des Mausklicks definieren den neuen Punkt p
moveTo(q): Zeichnet eine Verbindungslinie vom Punkt p (aktuelle Mausposition) zum Punkt q.
points.append(p): Fügt den Punkt p zu der Liste points
print(points): Zeigt die aktuelle Liste im Ausgabenfenster

 

Beispiel 5: Linke Maustaste erzeugt Punkte, rechte Maustaste erzeugt ein gefülltes Polygon

Die Ecken des Polygon werden per linken Mausklick erzeugt. Die Liste corner ist zu Beginn leer. Mit jedem Mausklick wird ein Punkt hinzugefügt und aktuelle Punktezahl angezeigt. Ein Klick mit der rechten Maustaste beendet die Punkterzeugung. in einer for-Schleife werden alle Punkte der Reihe nach zu einem Polygon verbunden und die Polygonfläche rot gefüllt.
# Tu13d.py

from gturtle import *

def onMousePressed(x, y):
    if isLeftMouseButton():
        p = (x, y)
        setPos(p)
        dot(8)        
        corner.append(p)
        print(len(corner))
    if isRightMouseButton():
        setFillColor("red")
        startPath()
        for q in corner:
             moveTo(q)
        fillPath()     
        
makeTurtle(mousePressed = onMousePressed)
hideTurtle()
corner=[]
Programmcode markieren (Ctrl+C kopieren, Ctrl+V einfügen)
 



Erklärungen zum Programmcode:

corner = []: Erzeugt eine leere Liste
corner.append(p): Fügt den Punkt p zur Liste corner hinzu
print(len(corner)): Anzahl Elemente der Liste (Länge der Liste) wird angezeigt
for q in corner:: Geht die Liste aller Punke durch

 

Beispiel 6: Fläche eines Polygons mit Monte Carlo-Methode bestimmen


Bereits im Kapitel Zufallszahlen wurde die Monte Carlo-Methode verwendet, um die Zahl Pi zu berechnen. Ähnlich kann man auch die Fläche eines beliebigen Polygons bestimmen. Die Eckpunkte des Polygons werden mit dem linken Mausklick festgelegt. Mit dem rechten Mausklick wird die Polygonfläche grau gefüllt und der "Zufallsregen" gestartet, h.d. man lässt z.B. n = 100 000 Zufallstropfen auf das Turtlefenster fallen.

Mit der Funktion getPixelColorStr() kann man herausfinden, ob die Farbe unter einem zufällig gewählten Punkt weiss oder grau ist. Die Tropfen in der grauen Fläche werden als Hits gezählt und rot markiert, die übrigen grün. Da es vorkommen kann, dass ein Punkt mehrmals getroffen wird, müssen bei den Treffern auch die bereits rot gefärbten Punkte als Hits gezählt werden.

 

 

 



Aus dem Verhältnis der Anzahl Treffer zu Anzahl aller Punkte, die man auf das Turtlefenster fallen lässt, lässt sich die Polygonfläche berechnen. Eine höhere Genauigkeit erreicht man, wenn man die Anzahl der Zufallspunkte erhöht. Das Ergebnis wird in der Statuszeile angezeigt.

Wenn d ie Funktion startRandomRain() im Callback der rechten Maustaste aufgerufen wird, erscheinen die Zufallspunkte alle gleichzeitig nach dem alle 100 000 Zufallstropfen gelandet sind. Unter verwendung von putSleep() und wakeUp() werden die Zufallstropfen "animiert" eins nach dem anderen dargestellt. Der Befehl startRundomRain() wird im Hauptprogramm mit putSleep() angehalten und gestartet, nach dem im Callback der rechten Maustaste wakeUp() aufgerufen wurde. Testen Sie den Unterschied, indem Sie startRandomRain() im Callback aktivieren und die wakeUp() und die letzten zwei Zeilen im Hauptprogramm deaktivieren.

# Tu13e.py

from gturtle import *
import random

def onMousePressed(x, y):
    if isLeftMouseButton():
        p = (x, y)
        setPos(p)
        dot(5)        
        corner.append(p)
    if isRightMouseButton():
        setFillColor("gray")
        startPath()
        for q in corner:
             moveTo(q)
        fillPath()
        #startRandomRain()
        wakeUp()     

def startRandomRain():
    nbHit = 0
    for i in range(n):            
        p = (random.randint (-300, 300), random.randint (-300, 300))
        setPos(p)
        color = getPixelColorStr() 
        if color == "white":
            setPenColor("green")                
            dot(2)
        if color == "gray" or color == "red":
            nbHit += 1
            setPenColor("red")                
            dot(2)
    setStatusText("#hits: " + str(nbHit) + " of " + str(n) 
                + " = " + str(nbHit/n * 100) + " % of windowarea") 
                               
makeTurtle(mousePressed = onMousePressed)
addStatusBar(20)
setStatusText("Left click to select corners, right click to start dropping") 
setPenColor("gray")
hideTurtle()
corner=[]
n = 100000
putSleep()
startRandomRain()
Programmcode markieren (Ctrl+C kopieren, Ctrl+V einfügen)

Erklärungen zum Programmcode:

startRandomRain(): Erzeugung n Zufallspunkte
getPixelColorStr(): gibt die Hintergrundfarbe an der Turtleposition zurück
putSleep(): Hält den Programmablauf an, bis wakeUp() aufgerufen wird
wakeUp(): Führt angehaltenen Programmablauf weiter

 

Beispiel 6: Regenbogenfarben aus einer Farbenliste auswählen

Der Befehl X11Color.RAINBOW_COLORS() liefert eine Liste mit 40 Farben. Diese wird als Liste colors gespeichert. Mit einer for-Schleife geht man diese Liste duch und zeichnet jeweils eine senkrechte Linie mit der Breite 10 Pixel.

# Tu13f.py

from gturtle import *

makeTurtle()
colors = X11Color.RAINBOW_COLORS
hideTurtle()
setPenWidth(10)
x = -200
for i in range(40):
   setPenColor(colors[i])
   setPos(x + 10 * i, -200)
   forward(400)
Programmcode markieren (Ctrl+C kopieren, Ctrl+V einfügen)
 

Erklärungen zum Programmcode:

colors = X11Color.RAINBOW_COLORS() : Liste mit 40 Regenbogenfarben
colors[i] : Das i-te Element der Liste
setPenWidth(10) bewirkt, dass die gezeichneten linien 10 Pixel breit sind

 


Aufgaben Serie 13

1.


Erstelle eine Liste mit 8 Farben. Zeichne ein regelmässiges 8-eck, bei dem jede Seite eine andere Farbe hat und mit etwas dickeren Linien gezeichnet wird.

       
2.

Mit dem linken Mausklick werden beliebig viele Punkte gezeichnet und in einer Liste gespeichert. Klickt man mit der rechten Maustaste, so werden vom Punkt des Mausklicks aus Verbindungslinien zu allen gespeicherten Punkten gezeichnet.

 

       
3.

Im Beispiel 4 wird die Liste points per Mausklick mit neuen Punkten ergänzt und jeder neue Punkt mit allen Punkten der Liste verbunden. Ergänze das Programm so dass bei jedem Mausklick auch die Anzahl der Verbindungslinien gezänlt wird. Die Zählervariable n wird im Hauprogramm mit n = 0 initialisiert beim Zeichnen jeder Verbindungslinie um 1 erhöht.
Da n in der Funktion onMousePressed(x, y) verändert wird, muss sie als global definiert werden. Du muss also die Zeile global n einfügen.

def onMousePressed(x, y):
    global n
    p = (x, y)
    setPos(p)
    ......

Vergleiche das Ergenbis mit der kombinatirischen Formel n * (n - 1) / 2.

 


       
4.

Erstelle eine Liste colors mit 8 Farben. Definiere eine Funktion line(color, length), der eine farbige Linie zeichnet. Zeichnen Sie eine Spirale, so wie im Bild rechts. Nach jeder gezeichneten Strecke wird die nächste Farbe aus der Liste colors genommen. Nach dem man die letzte farbe genommen hat, beginnt man wieder mit der ersten Farbe. 

 

 

       
5.

colors = X11Color.RAINBOW_COLORS
liefert eine Liste mit 40 Regebogenfarben. Gehe diese Liste mit einer for-Schleife durch und zeichne für jede Farbe eine 10 Pixel breite senkrechte Linie.

 

 

 

 



Zusatzstoff: Sortieralgorithmen

Sortieralgorithmen gehören zu den wichtigsten und meist verwendeten Verfahren der Informatik. Obwohl in vielen Programmiersprachen, so auch in Python, vordefinierte Sortierfunktionen existieren, gehören die Konzepte des Sortierens zum Standardwissen, denn es gibt immer wieder Situationen, in welchen man das Sortieren selbst implementieren muss.

Beispiel 6: Eine Liste mit n Elementen mit BubbleSort der Grösse nach ordnen

Die Sortierung mit BubbleSort-Algorithmus erfolgt wie folgt:

# BubleSort1.py

def bubbleSort(li):
    n = len(li)
    for i in range(n - 1, 0, -1):
        for k in range(i):
            if li[k] > li[k + 1]:
                li[k + 1],li[k] =  li[k],li[k + 1]
                 
li = [85, 34, 57, 13, 25, 39, 44, 7, 68, 30]
bubbleSort(li)
print(li)        
Programmcode markieren (Ctrl+C kopieren, Ctrl+V einfügen)

Ergebnis:
[7, 13, 25, 30, 34, 39, 44, 57, 68, 85]

Erklärungen zum Programmcode:
len(li): Anzahl Elemente der Liste li
for i in range(n - 1, 0, -1): Zuerst die ersten n-1 Elemente durchgehen, dann die ersten n-2 Element, n-3 Elementen usw.
li[k + 1], li[k] = li[k], li[k + 1]): Vertauscht die Reihenfolge der zwei Elemente der Liste li

 

Beispiel 7: Grafische Darstellung des BubbleSort-Algorithmus

n zufällig gewählte Zahlen zwischen 1 und 500 werden mit dem BubbleSort-Algorithmus sortiert. Um den Sortiervorgang grafisch darzustellen, zeichnet man für jede Zahl einen Balken, dessen Höhe in Pixel der Zufallszahl entspricht. Danach wird die Liste sortiert und die Balken nach jedem Sortierungsschritt neu dargestellt.

Die Funktion drawBar(s) zeichnet einen Balken der Länge s.
Die Funktion drawAllBars() zeichnet alle Balken.

 

 

# BubbleSort2.py

from gturtle import *
from random import randint

d = 10
n = 59

def createRandomBars():
    for i in range(n):
        s = randint(1, 500)
        li.append(s) 
    drawAllBars()

def drawBar(s):
    left(90)
    penDown()
    forward(s)
    back(s)
    penUp()
    right(90)
    
def drawAllBars():
    clear()
    setPos(-290, -250)
    for s in li: 
        drawBar(s)        
        forward(d)
    
def bubbleSort():
    for i in range(n-1, 0, -1):
        for k in range(0, i):
            if li[k] > li[k + 1]:
                li[k + 1],li[k] =  li[k],li[k + 1]
                drawAllBars()
                repaint()
                Turtle.sleep(10)                        

makeTurtle()
enableRepaint(False)
ht()
right(90)
setPenWidth(8)
li = []
createRandomBars()
bubbleSort()
Programmcode markieren (Ctrl+C kopieren, Ctrl+V einfügen)

Erklärungen zum Programmcode:

enableRepaint(False): verhindert das automatische Rendern
repaint(): stellt die ganze Grafik auf dem Bildschirm dar
Turtle.sleep(10): damit man das Sortieren bessert verfolgen kann, wird das Programm nach jedem Sortierdurchgang 10 ms angehalten

 

Beispiel 8: n Farbkugeln mit BubbleSort nach Regebogen-Spektrum sortieren

Zu Beginn werden n Kugeln in zufällig gewählten Regenbogenfarben gezeichnet. Damit die Farben nach dem Regebogenspektrum sortiert werden können, müssen sie in das HSB-Format konvertiert werden. Im HSB-Format wird jede Farbe mit den folgenden drei Komponenten angegeben: H: Farbton, S: Sättigung, B: Helligkeit. Für die Sortierung braucht man nur den Farbton (hsb[0]). Dieser wird mit einem Winkel im HSB-Farbkreis definiert (0° entspricht der Farbe rot).

Ergebnis:

 

HSB-Farbraum

 


# BubbleSort3.py

from gturtle import *
from random import randint

d = 15
n = 41

def createRandomDots():
    for i in range(n):
        c = makeColor("rainbow", randint(10, 90) / 100)
        li.append(c)
    drawAllDots()    
        
def drawAllDots():
    setPos(-295, 0)
    for c in li:
        setPenColor(c)
        dot(d - 1)
        forward(d)    

def getHsb(c):
    hsb = Color.RGBtoHSB(c.getRed(), c.getGreen(), c.getBlue(), [0, 0, 0])
    return hsb[0]
   
def bubbleSort():
    for i in range(n - 1, 0, -1):
        for k in range(i):
            if getHsb(li[k]) > getHsb(li[k + 1]):
                li[k + 1],li[k] =  li[k],li[k + 1]                
                drawAllDots()
                repaint()
                Turtle.sleep(10)
 
makeTurtle()
clear("black")
enableRepaint(False)
right(90)
li = []
createRandomDots()
bubbleSort()
Programmcode markieren (Ctrl+C kopieren, Ctrl+V einfügen)

Erklärungen zum Programmcode:

makeColor("rainbow", randint(10, 90) / 100): erzeugt eine zufällige Regenbogenfarbe
RGBtoHSB(): konvertiert eine RGB-Farbe zu
Turtle.sleep(10): damit man das Sortieren bessert verfolgen kann, wird das Programm nach jedem Sortierdurchgang 10 ms angehalten

 

Beispiel 9: QuickSort-Algorithmus

Der BubbleSort-Algorithmus ist einfach nachvollziehbar, ist aber nicht so effizient. In der Praxis werden deshalb effizientere Sortierverfahren verwendet, wie z.Bsp. QuickSort.

Der Programmcode ist einiges komplizierter als bei BubbleSort und wird an dieser Stelle nur als Demonstration aufgeführt, damit man die die Geschwindigkeit beider Sortierverfahren vergleichen kann. Eine Beschreibung des Algorithmus findet man beispielsweise auf Wikipedia. [https://de.wikipedia.org/wiki/Quicksort]

 

 

 

 

# QuickSort.py

from gturtle import *
from random import randint

d = 10
n = 59

def createRandomBars():
    for i in range(n):
        s = randint(1, 500)
        li.append(s) 
    drawAllBars(li)

def drawBar(s):
    left(90)
    penDown()
    forward(s)
    back(s)
    penUp()
    right(90)
    
def drawAllBars(li):
    clear()
    setPos(-290, -250)
    for s in li: 
        drawBar(s)        
        forward(d)
    
def quickSort(li):
   quickSortHelper(li,0,len(li)-1)

def quickSortHelper(li,first,last):
   if first<last:
       splitpoint = partition(li,first,last)
       quickSortHelper(li,first,splitpoint-1)
       quickSortHelper(li,splitpoint+1,last)

def partition(li,first,last):
   pivotvalue = li[first]
   leftmark = first+1
   rightmark = last
   done = False
   while not done:
       while leftmark <= rightmark and li[leftmark] <= pivotvalue:
           leftmark = leftmark + 1
       while li[rightmark] >= pivotvalue and rightmark >= leftmark:
           rightmark = rightmark -1
       if rightmark < leftmark:
           done = True
       else:
           temp = li[leftmark]
           li[leftmark] = li[rightmark]
           li[rightmark] = temp
   temp = li[first]
   li[first] = li[rightmark]
   li[rightmark] = temp
   drawAllBars(li)
   repaint()
   Turtle.sleep(10)     
   return rightmark     

makeTurtle()
enableRepaint(False)
ht()
right(90)
setPenWidth(8)
li = []
createRandomBars()
quickSort(li)
Programmcode markieren (Ctrl+C kopieren, Ctrl+V einfügen)

 


Aufgaben

6.

In Python gibt es eine eingebaute Funktion sort().
li.sort() sortiert die Liste li.
Verwende im Beispiel 7 (BubbleSort2.py) die Funktion sort() anstelle des BubleSort-Algorithmus. Du kannst allerdings nur die Start- und End-Situation darstellen. Auf die fortlaufende Animation muss du verzichten.


7.

colors = X11Color.RAINBOW_COLORS
liefert eine Liste mit 40 Regenbogenfarben. Ändere das unten stehenden Programm, so dass die Grafik in Regenbogenfarben gezeichnet wird.

from gturtle import *
makeTurtle()
hideTurtle()
s = 5
repeat 200:    
   forward(s)
   left(70)
   s = s + 1

Du gehst die Liste colors durch und zeichnest jeweils 5 Strecken mit der gleichen Farbe.

 

 

colors1 = list(reversed(colors))
liefert eine Liste, in der die Faben in der umgekehrten Reihenfolge angeordnet sind. Zeichne eine Grafik, die die Farben der Liste colors1 durchläuft.



Die wichtigsten Operationen mit Listen

 

li = [1, 2, 3, 4]

li = [1, "a", [7 , 5]]

li[i]

li[start:end]

li[start:end:step]

li[start:]

li[:end]

li.append(element)

li.insert(i, element)

li.extend(li2)

li.index(element)

li.pop(i)

pop()

li1 + li2

li1 += li2

li * 4

[0] * 4

len(li)

del li[i]

del li[start:end]

del li[:]

list(reversed(li))

li.sort() 

x in li

x not in li

li[k+1], li[k] = li[k], li[k+1]

Liste mit den Zahlen 1, 2, 3, 4 definieren

Liste mit unterschiedlichen Datentypen definieren

Auf Listenelement mit Index i zugreifen

Neue Teilliste mit Elementen start bis end,  aber ohne end

Neue Teilliste mit Elementen start bis end mit Schritt step

Neue Teilliste mit allen Elementen von start an

Neue Teilliste von ersten Element bis end, aber ohne end

Anfügen ans Ende

Einfügen an Stelle i (Element i rutscht nach rechts)

Elemente aus li2 anfügen (Konkatenation)

Sucht das erste Vorkommen und gibt dessen Index zurück

Entfernt das Element mit Index i und gibt es zuück

Entfernt das letzte Element und gibt es zurück

Gibt die Konkatenation von li1 und li2 in neuer Liste zurück

Ersetzt li1 durch die Konkatenation von li1 und li2

Neue Liste mit Elementen von li viermal wiederholt

Neue Liste mit der Länge 4 (jedes Element Zahl 0)

Gibt die Anzahl Listenelemente zurück

Entfernt das Element mit Index i

Entfernt alle Elemente von start bis end, aber ohne end

Entfernt alle Elemente, es bleibt eine leere Liste

Kehrt die Liste li um (letztes Element wird das erste)

Sortiert die Liste (Vergleich mit Standardverfahren)

Gibt True zurück, falls x in der Liste enthalten ist

Gibt True zurück, falls x nicht in der Liste enthalten ist

Vertauscht die Reihenfolge zwei nacheinanderfolgenden Elemente