efinf:blcks2017:jython:lektionen

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
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
 
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?
keycode.py
from gturtle import *
# notwending, weil getKeyCodeWait() aus gturtle ist.
makeTurtle()
 
print(getKeyCodeWait())
 
# oder
 
while True: 
    print(getKeyCodeWait())
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.

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 "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:

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")

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
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)
Farbwechsel
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")
Primzahlen
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))
Ganzzahl Operationen

Die Operationen / / und % sind nicht nur praktischer sonder auch einiges schneller:

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))

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

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]

Bitte zusätzlich noch diese 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.

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")

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

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)

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 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
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
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)))))

Aufgaben Teil 1

Die Aufgaben Teil 1 sind korrigiert in One Note

Aufgaben Teil 2

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)
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
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)
  • efinf/blcks2017/jython/lektionen.txt
  • Last modified: 2017/10/02 22:05
  • by Simon Knaus