==== L3 ==== from gturtle import * makeTurtle() # Turtle verstecken ht() s = 2 repeat 100: forward(s) left(90) # turtle weiter als 20 vom ursprung und weniger weit als 30: bitte grün if distance(0,0) > 20 and distance(0,0) < 30 : setPenColor("green") # sonst einfach blau else: setPenColor("blue") s = s + 2 from gturtle import * makeTurtle() # Variable s für die Seitenlänge s = 2 # Funktion segment mit zwei Parametern width und angle def segment(width, angle): forward(width) left(angle) repeat 20: segment(s) s = s + 2 ==== L4 ==== # Rekursive Definition Fibonacci Zahlen def fibonacci(n): #f_0 = 1 if n == 0: return(0) #f_1 = 1 elif n == 1: return(1) # f_n = f_n-1 + f_n-2 else: return(fibonacci(n-1)+fibonacci(n-2)) #1.618 goldener schnitt goldensection = (sqrt(5)+1)/2 n = 2 #solange fibonacci ausrechnen, bis Quotient auf 0.0001 am goldenen Schnitt ist. while abs(fibonacci(n)/fibonacci(n-1) - goldensection) > 0.00001: print(fibonacci(n)) n += 1 #n wird um 1 erhöht äquivalent zu n = n+1 # Frage: ist das ''intelligent'' programmiert? ==== L5 ==== from gturtle import * # notwending, weil getKeyCodeWait() aus gturtle ist. makeTurtle() print(getKeyCodeWait()) # oder while True: print(getKeyCodeWait()) a = 12 #globale Variable def funprint(): print(a) # 'lesezugriff' globale Variablen b=2*a # wird lokal verändert print(b) def funchange(): a=14 #lokale Variable, ändert globale Variable a nicht print(a) def funchangeglobal(): global a #welche globalen Variablen möchte ich in Funktion verwenden a = 14 #verändert globale Variable a print(a) funprint() print(a) #Ausgabe globale Variable funchange() print(a) #Ausgabe globale Variable funchangeglobal() print(a) #Ausgabe globale Variable #Achtung: Globale Variablen zurückhaltend einsetzen. ==== L6 ==== Take-Aways Hausaufagben: * Namen von Funktionen werden klein geschrieben. * Konvention von Python: Falls notwendig mit Underscore zur Klärung. Bsp ''def move():'' oder ''def move_forward_fast():'' * Konvention von TigerJython: Falls notwending [[https://en.wikipedia.org/wiki/Camel_case|"Camel-Style"]] zur Klärung. Bsp ''def moveForwardFast():'' * Generelle Praxis: "Englisch programmieren". Ja oder Nein? * If-Statements: Wenn inhaltlich sinnvoll mehrere Kriterien mit ''or'' und ''and'' verknüpfen * Nicht per Mail abgeben. * Divisionsrest: %, Ganzzahldivision / / Besprechung Aufgabe 2.10: from gturtle import * # Keycodes der Tasten definieren XLETTER = 88 LEFT = 37 RIGHT = 39 UP = 38 DOWN = 40 # Funktionsdefinition Key Listener def onKeyPressed(key): global stopit if key == LEFT: setHeading(-90) elif key == RIGHT: setHeading(90) elif key == UP: setHeading(0) elif key == DOWN: setHeading(180) elif key == XLETTER: stopit = True # Turtle initalisieren makeTurtle(keyPressed = onKeyPressed) # globale Variable zum Schlaufen--Abbruch stopit = False # halbe Breite und halbe Höhe h = getPlaygroundHeight()/2 w = getPlaygroundWidth()/2 # Turtle bewegen while True: forward(10) print(getPos()) #Position der Turtle # wenn eines der drei Abbruch-Kriterien erfüllt ist: break if stopit or abs(getX()>w) or abs(getY())>h: break # wenn Programm regulär beendet wird, wird "habe fertig" als Reverenz an Trappatoni ausgegeben print("Habe fertig") ==== L7 ==== ==== L8 ==== === Hausaufgaben === Take-Aways Hausaufagben: * Unnötige Operationen / Iteration etc. vermeiden * Standard-Variablen für Leserlichkeit verwenden (i,j,k anstelle von I, II, III) * Aufgaben genau lesen resp. rückfragen. == Strukturiertes Progammieren == import math from gpanel import * makeGPanel(-10, 10, -10, 10) def stern(x, y, r): fillTriangle(x - math.sqrt(3)/2 * r, y - r/2, x + math.sqrt(3)/2 * r, y - r/2, x, y + r); fillTriangle(x - math.sqrt(3)/2 * r, y + r/2, x + math.sqrt(3)/2 * r, y + r/2, x, y - r); stern(0, 0, 3) == Farbwechsel == from gturtle import * # Keycodes der Tasten definieren XLETTER = 88 LEFT = 37 RIGHT = 39 UP = 38 DOWN = 40 # Funktion, welche die Farbe auf Grund x und y definiert def changeColor(x,y): distance = sqrt(x*x+y*y) returncolor = "brown" if(distance < 100): returncolor = "blue" elif(distance < 200): returncolor = "green" elif(distance < 300): returncolor = "yellow" ## was würde passieren, wenn die Reihenfolge von 300, 200, 100 umgekehrt würde? return returncolor # Funktionsdefinition Key Listener def onKeyPressed(key): global stopit if key == LEFT: setHeading(-90) elif key == RIGHT: setHeading(90) elif key == UP: setHeading(0) elif key == DOWN: setHeading(180) elif key == XLETTER: stopit = True # Turtle initalisieren makeTurtle(keyPressed = onKeyPressed) # globale Variable zum Schlaufen--Abbruch stopit = False # halbe Breite und halbe Höhe h = getPlaygroundHeight()/2 w = getPlaygroundWidth()/2 # Turtle bewegen while True: forward(10) print(getPos()) #Position der Turtle #Aufruf der Funktion changeColor setColor(changeColor(getX(),getY())) # wenn eines der drei Abbruch-Kriterien erfüllt ist: break if stopit or abs(getX()>w) or abs(getY())>h: break # wenn Programm regulär beendet wird, wird "habe fertig" als Reverenz an Trappatoni ausgegeben print("Habe fertig") == Primzahlen == # Um Ausführungszeit zu messen import time # Halbwegs effiziente Version def checkPrime1(n,printout=True): for i in range(2,n+1): isPrime = True for j in range(2,int(sqrt(i))+1): if i%j == 0: isPrime = False break if(isPrime): if(printout): print(i) # Ineffiziente Version def checkPrime2(n,printout=True): for i in range(2,n+1): isPrime = True for j in range(2,i): if i%j == 0: isPrime = False if(isPrime): if(printout): print(i) ## Zeit messen für checkPrimes1 t0 = time.clock() repeat 100: checkPrime1(1001,False) print((time.clock()-t0)) ## Nochmals messen für checkPrimes2 t0 = time.clock() repeat 100: checkPrime2(1001,False) print((time.clock()-t0)) == Ganzzahl Operationen == Die Operationen / / und % sind nicht nur praktischer sonder auch einiges schneller: # Um Ausführungszeit zu messen import time t0 = time.clock() a = 0 repeat 1000000: a = (14/2 == (int(14/2))) print((time.clock()-t0)) t0 = time.clock() a = 0 repeat 1000000: a = (14%2 == 0) print((time.clock()-t0)) ==== L10 ==== === Feebdack === Coding Style * Funktionen werden klein geschrieben. Idealerweise auch als Verb und nicht als Subjekt, bsp. ''rotate'' statt ''rotation'' * Listennamen sind idealerweise im Plural. Dann ist bereits aus dem Variabelnamen klar, dass es sich um eine Liste handelt. * Achtung mit mutable und imuutable data types. === Mutable und immutable data types === x = 'foo' y = x print x # foo y += 'bar' print x # foo print y # foobar x = [1, 2, 3] y = x print x # [1, 2, 3] y += [3, 2, 1] print x # [1, 2, 3, 3, 2, 1] print y # [1, 2, 3, 3, 2, 1] def fun(val): val = 'bar' x = 'foo' print x # foo fun(x) print x # foo def fun(val): val[1]=-1 x = [1, 2, 3] print x # [1, 2, 3] fun(x) print x # [1, -1, 3] def fun(val): val = [1,2,3] val[1] = -2 x = [1, 2, 3] print x # [1, 2, 3] fun(x) print x # [1,2, 3] Bitte zusätzlich noch diese [[http://bjc.berkeley.edu/bjc-r/cur/programming/python/list_mutability.html|Ergänzung]] durchlesen. Lösungen dafür sind: * Vom Modul ''copy'' ''copy.deepcopy'' verwenden, d.h. ''neueliste = copy.deepcopy(alteliste)'' * Jeweils eine neue Liste verwenden, d.h. ''neueliste = [1,2,3,4]'' * Das Verhalten <>. Achtung, bei Listen von Listen tritt dies doppelt auf. === Module === Wir haben bis jetzt schon mit Modulen gearbeitet. Diese haben wir entweder mit ''import modulename'' oder mit ''from modulname import *'' importiert. Man kann auch eigene Module schreiben, die Funktionen beinhaltet. Z.B. könnte man das Modul ''efinfo.py'' schreiben, welches alle Funktionen u.ä. enthält, welche wir für 2048 benutzen. import sys def printDoubleLists(lists): for i in range(len(lists)): for j in range(len(lists[i])): sys.stdout.write(str(lists[i][j])) sys.stdout.write("\t") sys.stdout.write("\n") Nachher könnte die Funktion wie folgt aufgerufen werden. Achtung ''efinfo.py'' muss im Pfad oder im gleichen Verzeichnis wie die ausgeführte Datei sein. import efinfo tiles = [[4, -1, 4, 8], [16, 32, 64, 128], [256, -1, -1, 2048], [-1, -1, -1, -1]] efinfo.printDoubleLists(tiles) # oder from efinfo import * tiles = [[4, -1, 4, 8], [16, 32, 64, 128], [256, -1, -1, 2048], [-1, -1, -1, -1]] printDoubleLists(tiles) === Lernziele === * Alle Lernziele vom Lehrmittel der bearbeiten Kapitel (d.h., z.B. ohne Rekursion, ohne Objekte im Kapitel 2) * Zusätzlich dazu: * Programme mit gechachtelten Schlaufen lesen und schreiben können * Programme mit geschachtelten Listen lesen und schreiben können == Beispiel 1 == Was ist die Ausgabe des untenstehenden Programms? Was die Idee? numbers = [[4, -1, 4, 8], [16, 32, 64, 128], [256, -1, -1, 2048], [-1, -1, 1, -1]] result = [0]*len(numbers) for i in range(len(numbers)): for j in range(len(numbers[i])): result[i]+=numbers[i][j] print(result) == Beispiel 2 == Was ist die Ausgabe des untenstehenden Programms? def dummyfunction(c,d): e = 2+d e += c foofunction(c,e) print(e) if e>0: print("Alles jut") else: print("So'n Mist hier") def foofunction(c,d): e=0 for i in range(c,d): e+=i print(e) dummyfunction(2,1) === Lösungen === from efinfo import * import copy tiles = [[4, -1, 4, 8], [16, 32, 64, 128], [256, -1, -1, 2048], [-1, -1, -1, -1]] def shiftAndCollapseLine(inline): ##Idee: Kippen, ersetzen, kippen #einmal kippen #idee: alle nicht -1 sammeln, dann -1 wieder anhängen #leere tiles temp = [] #sammeln for j in inline: if j != -1: temp.append(j) #anhängen: Python'esquer Weg zum Anhängen temp += [-1] * inline.count(-1) #tiles umdrehen temp.reverse() #identicshe zellen verdoppeln und durch -1 ersetzen for j in range(len(temp) - 1): if temp[j] == temp[j + 1] and temp[j] != -1: temp[j+1] = 2 * temp[j] temp[j] = -1 inline=[] #wieder sammeln und anhängen for j in temp: if j != -1: inline.append(j) inline+=[-1] * temp.count(-1) #tiles umdrehen inline.reverse() return(inline) def shiftAndCollapseGrid(tiles): # 'leere' tiles mit länge von tiles temp = [-1]*len(tiles) for i in range(len(tiles)): temp[i] = shiftAndCollapseLine(tiles[i]) return(temp) def rotateGrid(tiles): returnlist = copy.deepcopy(tiles) #sehr Pythonish return(list(map(list, zip(*returnlist[::-1])))) printDoubleLists(tiles) print repeat 4: tiles = rotateGrid(tiles) printDoubleLists(tiles) ==== L11 ==== Auf Grund der Diskussionen in den Gruppen nochmals ein Brush-up: === Scoping (Lebensdauer von Variablen) === # Globale Variable a a = 0 if a == 0: # Immer noch eine globale Variable b b = 1 def myFunction(c): # d ist eine lokale Variable, c ist Argument der Funktion d = 3 print(c) print(d) return(d+c) # Funktionsaufruf mit Arugment 7, der Rückgabewert wird der _globalen_ Variable e zugewiesen e = myFunction(7) # e = 10 # a,b,e exisiteren noch im Speicher und können ausgegeben werden print('a') print(a) print('b') print(b) print('e') print(e) # c und d waren lokale Variablen und ergeben einen Fehler. print(c) print(d) Möchte man eine globale Variable innerhalb einer Funktion verändern, braucht es den Aufruf ''global variablename'' als erste Zeile in der Funktion. Siehe auch [[efinf:blcks2017:jython:lektionen#l5|Lektion 5]]. *Achtung*: Das gilt genauso, wenn der Rückgabewert / die Variable ein anderer Typ (String, Boolean, Liste, etc.) ist. === Assignment Operatoren === # In Ordnung a = 3 i = -3 # Nicht in Ordnung. Wenn Vergleich, dann == 3 = 4 3 = a a + b = 3 #In Ordnung i = i + 1 i += 1 # äquivalent zu oben # es gibt ebenfalls +=, -=, *=, /=, %=, //=, **= a %= 3 a = a % 3 ==== L12 ==== import random def randomMatrix(zeilen, spalten): matrix = [] for i in range(zeilen): zeile = [] for j in range(spalten): zeile.append(random.randint(0,1000)) matrix.append(zeile) zeile = [] return matrix from gpanel import * from math import * makeGPanel(-50,50, -50, 50) def drawNumbers(n): for i in range(1,n+1): # x und y Koordinate des Punktes. # x = cos(winkel)*radius, # y = sin(winkel)*radius # der Winkel ist dabei 2*Pi, entspricht 360°, # dividiert durch n mal die Zahl i. x = cos(2*pi/n*i)*40 y = sin(2*pi/n*i)*40 move(x,y) # Kreisfarbe setColor("green") fillCircle(2) # Textfarbe setColor("black") text(x,y,str(i)) drawNumbers(20) def checkPrime(i): return((all(map(lambda x: i%x!=0, range(2,i))))) ==== L13 ==== === Aufgaben Teil 1 === Die Aufgaben Teil 1 sind korrigiert in One Note === Aufgaben Teil 2 === def dummyfunction(n): for i in range(1,n+1): print i if i%15 == 0: #wichtig: zuerst modulo 15 teste! print "TuTuTaTa" elif i%3 == 0: print "TaTa" elif i%5 == 0: print "TuTu" dummyfunction(30) import random def randomMatrix(zeilen, spalten): matrix = [] for i in range(zeilen): zeile = [] for j in range(spalten): zeile.append(random.randint(0,1000)) matrix.append(zeile) zeile = [] return matrix #i meineMatrix = randomMatrix(3,5) # ii def summe(matrix): sumvar = 0 # durch matrix loopen for i in range(len(matrix)): for j in range(len(matrix[i])): # jedes element addieren sumvar += matrix[i][j] return sumvar #iii def durchschnitt(matrix): sumvar = 0 count = 0 # durch matrix loopen for i in range(len(matrix)): for j in range(len(matrix[i])): # jedes element addieren und counter erhöhen sumvar += matrix[i][j] count += 1 return sumvar/count #iv print(durchschnitt(randomMatrix(100,100))) #oder print(summe(randomMatrix(100,100))/(100**2)) # der durchschnitt nähert sich 500 from gpanel import * from math import * makeGPanel(-50,50, -50, 50) #i def checkPrime(n): isPrime = True for j in range(2,int(sqrt(n))+1): if n%j == 0: isPrime = False break return(isPrime) def drawNumbers(n): for i in range(1,n+1): # x und y Koordinate des Punktes. # x = cos(winkel)*radius, # y = sin(winkel)*radius # der Winkel ist dabei 2*Pi, entspricht 360°, # dividiert durch n mal die Zahl i. x = cos(2*pi/n*i)*40 y = sin(2*pi/n*i)*40 move(x,y) # Kreisfarbe # Aufgaben Teil ii) if(checkPrime(i)): setColor("green") else: setColor("orange") fillCircle(2) # Textfarbe setColor("black") text(x,y,str(i)) # Aufgabe Teil iv) for j in range(1,n+1): if j % i == 0 or i%j == 0: xn = cos(2*pi/n*j)*40 yn = sin(2*pi/n*j)*40 line(x,y,xn,yn) else: continue drawNumbers(30)