efinf:blcks2017:jython:lektionen

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
efinf:blcks2017:jython:lektionen [2017/09/19 12:30] Simon Knausefinf:blcks2017:jython:lektionen [2017/10/02 20:05] (current) Simon Knaus
Line 1: Line 1:
 +==== L3 ====
 +<code  python ifdand.py>
 +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
 +</code>
 +
 +
 +<code python variable.py>
 +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
 + </code>
 +
 +==== L4 ====
 +<code python fibonacci.py>
 +# 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?
 +</code>
 +
 +==== L5 ====
 +<code python keycode.py>
 +from gturtle import *
 +# notwending, weil getKeyCodeWait() aus gturtle ist.
 +makeTurtle()
 +
 +print(getKeyCodeWait())
 +
 +# oder
 +
 +while True: 
 +    print(getKeyCodeWait())
 +</code>
 +<code python globale_variablen.py>
 +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.
 +</code>
 +==== 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:
 +<code python turtle_exit.py>
 +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")
 +</code>
 +
 +==== 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 == 
 +<code python stern.py>
 +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)
 +</code>
 +== Farbwechsel ==
 +<code python changecolor.py>
 +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")
 +</code>
 +== Primzahlen ==
 +<code python primes.py>
 +# 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))
 +</code>
 +== Ganzzahl Operationen ==
 +Die Operationen / / und % sind nicht nur praktischer sonder auch einiges schneller:
 +
 +
 +<code python ganzzahl.py>
 +# 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))
 +</code>
 +
 +==== 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 ===
 +<code python example.py>
 +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]
 +</code> 
 +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 <<in Kauf nehmen>>. 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.
 +<code python efinfo.py>
 +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")
 +</code>
 +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.
 +<code python>
 +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)
 +</code>
 +=== 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?
 +<code python>
 +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)
 +</code>
 +== Beispiel 2 ==
 +Was ist die Ausgabe des untenstehenden Programms?
 +<code python>
 +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)
 +</code>
 +=== Lösungen === 
 +<code python skeleton.py>
 +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)
 +</code>
 +
 +==== L11 ====
 +Auf Grund der Diskussionen in den Gruppen nochmals ein Brush-up:
 +
 +=== Scoping (Lebensdauer von Variablen) ===
 +<code python>
 +# 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)
 +</code>
 +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 ===
 +<code python>
 +# 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
 +</code>
 +==== L12 ====
 +<code python afg8.py>
 +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
 +</code>
 +
 +<code python afg9.py>
 +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)))))
 +
 +</code>
 +==== L13 ====
 +=== Aufgaben Teil 1 === 
 +Die Aufgaben Teil 1 sind korrigiert in One Note
 +=== Aufgaben Teil 2 === 
 +<code python afg7.py>
 +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)
 +</code>
 +<code python afg8.py>
 +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
 +</code>
 +<code python afg9.py>
 +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) 
 +
 +</code>