Top Banner
Diskrete Modellierung Wintersemester 2018/19 Martin Mundhenk Uni Jena, Institut f¨ ur Informatik 5. November 2018
25

Diskrete Modellierung - Wintersemester 2018/19 · Prinzip: Kapselung von Daten in Objekten ... x * y mul (self,other) Vektor-Produkt von x und y x.richtung() Einheitsvektor mit der

Aug 09, 2019

Download

Documents

haquynh
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Diskrete Modellierung - Wintersemester 2018/19 · Prinzip: Kapselung von Daten in Objekten ... x * y mul (self,other) Vektor-Produkt von x und y x.richtung() Einheitsvektor mit der

Diskrete Modellierung

Wintersemester 2018/19

Martin Mundhenk

Uni Jena, Institut fur Informatik

5. November 2018

Page 2: Diskrete Modellierung - Wintersemester 2018/19 · Prinzip: Kapselung von Daten in Objekten ... x * y mul (self,other) Vektor-Produkt von x und y x.richtung() Einheitsvektor mit der

3.3 Entwurf von Datentypen

Durch das Erzeugen von Datentypen

entwickelt der Programmierer eine eigene Sprache,

mit der uber die Daten”gesprochen“ werden kann.

Deshalb muss man beim Entwickeln einer Idee fur ein Programm das Ziel haben, die benotigten

Datentypen zu verstehen und zu designen.

In diesem Abschnitt werden wir (nochmal) betrachten, welche Moglichkeiten man hat, und wie

man beim Design einerseits die Implementierung des Datentyps und andererseits deren Benutzung

im Auge behalten muss.

Das werden wir am Beispiel des Datentyps Vector machen.

3.3.1

Page 3: Diskrete Modellierung - Wintersemester 2018/19 · Prinzip: Kapselung von Daten in Objekten ... x * y mul (self,other) Vektor-Produkt von x und y x.richtung() Einheitsvektor mit der

Vektoren und der Datentyp Vector

Mit Vektoren will man z.B. im dreidimensionalen Raum eine Kraft darstellen, die in einebestimmte Richtung wirkt.Die Große der Kraft wird durch einen Pfeil einer bestimmten Lange in die gegebene Richtungdargestellt.Zur Beschreibung des Vektors genugt die Angabe der Koordinaten seines Endpunktes (wenn derStartpunkt der Nullpunkt ist).

Dieses Konzept kann man sich in beliebigen Dimensionen vorstellen.Es wird ausfuhrlich in der Linearen Algebra untersucht.

3.3.2

Page 4: Diskrete Modellierung - Wintersemester 2018/19 · Prinzip: Kapselung von Daten in Objekten ... x * y mul (self,other) Vektor-Produkt von x und y x.richtung() Einheitsvektor mit der

Wir benutzen x zur Bezeichnung eines Vektors

und px0, x1, . . . , xn´1q zur Bezeichnung seiner Werte.

Beispiel: x “ p0, 3, 6.4,´2.5q, y “ p17, 4q , z “ p1, 2, 3, 4, 5, 6q .

Damit ist klar, welche Daten fur einen Vektor gespeichert werden mussen.

Variante 1: Speicherung eines Vektors als Array.Der Konstruktor wird mit einem Array a aufgerufen und nimmt es fur die Vektor-Daten.

# Definition der Klasse Vector

class Vector:

def __init__(self,a):

self._koordinaten = a

self._n = len(a)

def __str__(self):

return str(self._koordinaten)

# test.py benutzt Datentyp Vector

t = [1,2,3]

v = Vector(t)

print v

t[1] = 999

print v

# python test.py

# [1, 2, 3]

# [1, 999, 3]

Problem:Daten sind nicht gekapselt und konnen (versehentlich) von außen verandert werden!

3.3.3

Page 5: Diskrete Modellierung - Wintersemester 2018/19 · Prinzip: Kapselung von Daten in Objekten ... x * y mul (self,other) Vektor-Produkt von x und y x.richtung() Einheitsvektor mit der

Variante 2: Speicherung eines Vektors als Array.Der Konstruktor wird mit einem Array aufgerufen.Er legt eine Kopie des Arrays zum Speichern der Daten an.

# Definition der Klasse Vector

class Vector:

def __init__(self,a):

self._koordinaten = a[:]

self._n = len(a)

def __str__(self):

return str(self._koordinaten)

# test.py benutzt Datentyp Vector

t = [1,2,3]

v = Vector(t)

print v

t[1] = 999

print v

v._koordinaten[1] = 999

print v

# python test.py

# [1, 2, 3]

# [1, 2, 3]

# [1, 999, 3]

Die Daten des Objekts konnen jetzt nur noch”mutwillig“ verandert werden (gegen die Konvention).

3.3.4

Page 6: Diskrete Modellierung - Wintersemester 2018/19 · Prinzip: Kapselung von Daten in Objekten ... x * y mul (self,other) Vektor-Produkt von x und y x.richtung() Einheitsvektor mit der

Es besteht auch die Moglichkeit, Datentypen mit unveranderbaren Daten zu definieren. Dazu kann man deneingebauten Datentyp tuple benutzen. Er ist ahnlich wie array, aber man kann die Eintrage nicht andern.Variante 3: Speicherung eines Vektors als unveranderbares Tupel.

Der Konstruktor wird mit einem Array aufgerufen.Er legt ein tuple zum Speichern der Daten an.

# Definition der Klasse Vector

class Vector:

def __init__(self,a):

self._koordinaten = tuple(a)

self._n = len(a)

def __str__(self):

return str(self._koordinaten)

# test.py benutzt Datentyp Vector

t = [1,2,3]

v = Vector(t)

print v

t[1] = 999

print v

v._koordinaten[1] = 999

print v

# python test.py

# [1, 2, 3]

# [1, 2, 3]

# Traceback (most recent call last):

# File "vector3.py", line 21, in <module>

# if __name__=='__main__': test()

# File "vector3.py", line 18, in test

# v._koordinaten[1] = 999

# TypeError: 'tuple' object does not support item assignment3.3.5

Page 7: Diskrete Modellierung - Wintersemester 2018/19 · Prinzip: Kapselung von Daten in Objekten ... x * y mul (self,other) Vektor-Produkt von x und y x.richtung() Einheitsvektor mit der

Einschub: Der eingebaute Datentyp tuple

Teil der API:

Operation Beschreibungtuple(a) ein Tupel mit den gleichen Eintragen wie Array a

(a,b,c,...) ein Tupel mit den Eintragen a, b, c, . . .

t[i] der i-te Eintrag von Tupel t (kann nur gelesen werden)

len(t) die Anzahl der Eintrage im Tupel t

for v in t: Iteration uber die Eintrage im Tupel t

Weitere Beispiele:t = (1,2,3)

(x,y,z) = t tuple unpacking

tuple eignet sich zur Ruckgabe von Funktionswerten, die aus mehrerern einzelnen Wertenbestehen . . .

3.3.6

Page 8: Diskrete Modellierung - Wintersemester 2018/19 · Prinzip: Kapselung von Daten in Objekten ... x * y mul (self,other) Vektor-Produkt von x und y x.richtung() Einheitsvektor mit der

Bisher gesehene Entwurfs-Prinzipien und -Entscheidungen

Prinzip: Kapselung von Daten in Objekten

§ verbessert die Modularitat

§ verbessert die Klarheit des Client-Programms

§ verringert die Gefahr von Fehlern

Entscheidung: Daten im Objekt sind veranderbar bzw. unveranderbar

3.3.7

Page 9: Diskrete Modellierung - Wintersemester 2018/19 · Prinzip: Kapselung von Daten in Objekten ... x * y mul (self,other) Vektor-Produkt von x und y x.richtung() Einheitsvektor mit der

Die Vektor-Operationen

§ Addition: x` y “ px0 ` y0, x1 ` y1, . . . , xn´1 ` yn´1q

§ skalare Multiplikation: αx “ pαx0, αx1, . . . , αxn´1q

§ Vektor-Produkt: x ¨ y “ x0 ¨ y0 ` x1 ¨ y1 ` . . .` xn´1 ¨ yn´1

§ Große: |x| “a

x02 ` x12 ` . . .` xn´12

§ Richtung: x{|x| “ px0{|x|, x1{|x|, . . . , xn´1{|x|q

(Auf Englisch wird skalare Multiplikation durch scale product

und Vektor-Produkt durch dot product bezeichnet.)

3.3.8

Page 10: Diskrete Modellierung - Wintersemester 2018/19 · Prinzip: Kapselung von Daten in Objekten ... x * y mul (self,other) Vektor-Produkt von x und y x.richtung() Einheitsvektor mit der

Die API fur Vector

Operation spezielle Methode BeschreibungVector(a) init (self,a) ein neuer Vector mit Koordinaten aus dem Array a[]

x[i] getitem (self,i) i-te Koordinate von x

x + y add (self,other) Summe von x und y

x.skalar(alpha) skalare Multiplikation von float alpha und x

x * y mul (self,other) Vektor-Produkt von x und y

x.richtung() Einheitsvektor mit der gleichen Richtung wie x

abs(x) abs (self) Große von x

len(x) len (self) Lange von x

str(x) str (self) string-Darstellung von x

3.3.9

Page 11: Diskrete Modellierung - Wintersemester 2018/19 · Prinzip: Kapselung von Daten in Objekten ... x * y mul (self,other) Vektor-Produkt von x und y x.richtung() Einheitsvektor mit der

Prinzipien zum Entwurf von APIs

§ Die API soll nicht zu groß werden.

(Ausnahmen sind haufig benutzte eingebaute Datentypen wie z.B. str.)

§ Die API soll nicht zu schwer zum Implementieren sein.

§ Die Programme, die einen Datentyp benutzen, sollen einfach werden.

§ Die API soll unabhangig von den tatsachlichen Daten sein.

3.3.10

Page 12: Diskrete Modellierung - Wintersemester 2018/19 · Prinzip: Kapselung von Daten in Objekten ... x * y mul (self,other) Vektor-Produkt von x und y x.richtung() Einheitsvektor mit der

Polymorphismus und Overloading

Beim Implementieren von Methoden oder Funktionen denken wir haufig, dass sie mit Objektenbestimmter Typen aufgerufen werden.

Entgegengesetzt wollen wir aber manchmal auch, dass sie mit Objekten unterschiedlicher Typenbenutzt werden konnen.Solche Methoden (bzw. Funktionen) nennt man polymorph.

Overloading ist eine spezielle Art von Polymorphismus.Es erlaubt z.B., dass gleiche Operatoren abhangig vom Datentyp der Operanden unterschiedlicheImplementierungen haben.

class A:

def __init__(self,i):

self._i = i

def op(self):

print("Klasse A")

class B:

def __init__(self,i):

self._i = i

def op(self):

print("Klasse B")

# test.py

x = A(5)

x.op()

x = B(5)

x.op()

# python test.py

# Klasse A

# Klasse B3.3.11

Page 13: Diskrete Modellierung - Wintersemester 2018/19 · Prinzip: Kapselung von Daten in Objekten ... x * y mul (self,other) Vektor-Produkt von x und y x.richtung() Einheitsvektor mit der

Spezielle Methoden

Ein weiteres Beispiel fur Overloading sind die speziellen Methoden.

Sie erlauben, z.B. arithmetische Operatoren statt Methodenaufrufen zu verwenden.

class Vector:

def __init__(self,a):

self._koordinaten = tuple(a)

self._n = len(a)

def __add__(self,other):

ergebnis = stdarray.create1D(self._n,0)

for i in range(self._n):

ergebnis[i] = self._koordinaten[i] + other._koordinaten[i]

return Vector(ergebnis)

# test.py benutzt Vector

x = Vector([1,2,3])

y = Vector([4,5,6])

z = x + y

print(z)

# python test.py

# (5, 7, 9)3.3.12

Page 14: Diskrete Modellierung - Wintersemester 2018/19 · Prinzip: Kapselung von Daten in Objekten ... x * y mul (self,other) Vektor-Produkt von x und y x.richtung() Einheitsvektor mit der

Spezielle Methoden fur arithmetische Operatoren

3.3.13

Page 15: Diskrete Modellierung - Wintersemester 2018/19 · Prinzip: Kapselung von Daten in Objekten ... x * y mul (self,other) Vektor-Produkt von x und y x.richtung() Einheitsvektor mit der

Spezielle Methoden fur Gleichheit

Gleichheit von Referenzen is

Die Operatoren is bzw. is not prufen, ob zwei Referenzen gleich sind.

>>> a = [1,2]

>>> b = [1,2]

>>> c = a

>>> a is b

False

>>> a is c

True

>>> d = (1,2)

>>> a is d

False

is und is not sind auf alle Datentypen anwendbar.

3.3.14

Page 16: Diskrete Modellierung - Wintersemester 2018/19 · Prinzip: Kapselung von Daten in Objekten ... x * y mul (self,other) Vektor-Produkt von x und y x.richtung() Einheitsvektor mit der

Gleichheit der Werte des Objekts: ==

kann auf Objekte mit Wert vom gleichen Datentyp angewendet werden.Es kann durch die spezielle Methode eq () definiert werden.Ist sie nicht definiert, dann ersetzt Python es durch is .

class Charge1:

def __init__(self, x0, y0, q0):

self._xkoord = x0

self._ykoord = y0

self._ladung = q0

# test.py benutzt Charge1

c1 = Charge1(1,2,3)

c2 = Charge1(1,2,3)

print(c1==c2)

# test.py

# False

class Charge2:

def __init__(self, x0, y0, q0):

...

def __eq__(self,other):

if self._xkoord != other._xkoord: return False

if self._ykoord != other._ykoord: return False

if self._ladung != other._ladung: return False

return True

# test.py benutzt Charge2

c1 = Charge2(1,2,3)

c2 = Charge2(1,2,3)

print(c1==c2)

# test.py

# True

3.3.15

Page 17: Diskrete Modellierung - Wintersemester 2018/19 · Prinzip: Kapselung von Daten in Objekten ... x * y mul (self,other) Vektor-Produkt von x und y x.richtung() Einheitsvektor mit der

Hashing

Die eingebaute hash()-Funktion gibt fur jedes Objekt ein int zuruck –den sog. Hashcode. Sie kann durch die spezielle Methode hash() uberladen werden.Wir nennen ein Objekt hashbar, falls:

§ Die Gleichheitsoperation == ist auf das Objekt anwendbar.

§ Mittels == gleiche Objekte haben den gleichen Hashcode.

§ Der Hashcode eines Objekts andert sich nie.class Charge3:

def __init__(self, x0, y0, q0):

self._xkoord = x0

self._ykoord = y0

self._ladung = q0

def __eq__(self,other):

if self._xkoord != other._xkoord: return False

if self._ykoord != other._ykoord: return False

if self._ladung != other._ladung: return False

return True

def __hash__(self):

a = self._xkoord + 2*self._ykoord + 10*self._ladung

return int(a)

# test.py benutzt Charge3

c1 = Charge3(1,2,3)

c2 = Charge3(1,2,3)

print(c1 is c2)

print(hash(c1))

print(hash(c2))

# python3 test.py

# False

# 35

# 35

3.3.16

Page 18: Diskrete Modellierung - Wintersemester 2018/19 · Prinzip: Kapselung von Daten in Objekten ... x * y mul (self,other) Vektor-Produkt von x und y x.richtung() Einheitsvektor mit der

3.3.17

Page 19: Diskrete Modellierung - Wintersemester 2018/19 · Prinzip: Kapselung von Daten in Objekten ... x * y mul (self,other) Vektor-Produkt von x und y x.richtung() Einheitsvektor mit der

Spezielle Methoden fur weitere Vergleichsperatoren

3.3.18

Page 20: Diskrete Modellierung - Wintersemester 2018/19 · Prinzip: Kapselung von Daten in Objekten ... x * y mul (self,other) Vektor-Produkt von x und y x.richtung() Einheitsvektor mit der

Spezielle Methoden fur eingebaute Funktionen

Fast alle Operatoren – z.B. += – konnen uberladen werden.

Es gibt weitere spezielle Methoden, die wir spater noch benutzen werden.

3.3.19

Page 21: Diskrete Modellierung - Wintersemester 2018/19 · Prinzip: Kapselung von Daten in Objekten ... x * y mul (self,other) Vektor-Produkt von x und y x.richtung() Einheitsvektor mit der

Die Implementierung von Vector

import stdarray, math

class Vector:

def __init__(self,a):

self._koordinaten = tuple(a)

self._n = len(a)

def __add__(self,other):

ergebnis = stdarray.create1D(self._n,0)

for i in range(self._n):

ergebnis[i] = self._koordinaten[i] + other._koordinaten[i]

return Vector(ergebnis)

def skalar(self,alpha):

ergebnis = stdarray.create1D(self._n,0)

for i in range(self._n):

ergebnis[i] = alpha * self._koordinaten[i]

return Vector(ergebnis)

def __mul__(self,other):

...

3.3.20

Page 22: Diskrete Modellierung - Wintersemester 2018/19 · Prinzip: Kapselung von Daten in Objekten ... x * y mul (self,other) Vektor-Produkt von x und y x.richtung() Einheitsvektor mit der

def richtung(self):

return self.skalar(1.0/abs(self))

def __abs__(self):

...

def __len__(self):

return self._n

def __getitem__(self,i):

return self._koordinaten[i]

def __str__(self):

return str(self._koordinaten)

def test():

print abs(Vector([1,2,3]))

...

if __name__=='__main__': test()

3.3.21

Page 23: Diskrete Modellierung - Wintersemester 2018/19 · Prinzip: Kapselung von Daten in Objekten ... x * y mul (self,other) Vektor-Produkt von x und y x.richtung() Einheitsvektor mit der

Vererbung

Python unterstutzt die Definition von Beziehungen zwischen Klassen.

Man kann (neue) Klassen als Unterklassen bereits definierter (Ober-)Klassen definieren. Die Unterklassenerben Instanzen-Variablen und Methoden ihrer Oberklassen.

Dieses Konzept ist sehr umfangreich und wir begnugen uns mit einem (etwas murksigen) Beispiel auf der

nachsten Seite.

3.3.22

Page 24: Diskrete Modellierung - Wintersemester 2018/19 · Prinzip: Kapselung von Daten in Objekten ... x * y mul (self,other) Vektor-Produkt von x und y x.richtung() Einheitsvektor mit der

class Bruch:

# Klasse fur ungekurzte rationale Zahlen

def __init__(self, zaehler, nenner):

self._z = zaehler

self._n = nenner

def __str__(self):

return str(self._z) + " / " + str(self._n)

class gBruch(Bruch):

# Unterklasse von Bruch fur gekurzte Bruche

def _ggT(self):

a = self._z

b = self._n

while a%b != 0:

(a,b) = (b,a%b)

return b

def _kuerzen(self):

g = self._ggT()

self._z = self._z / g

self._n = self._n / g

def __str__(self):

self._kuerzen()

return Bruch.__str__(self)

# test.py benutzt Bruch und gBruch

a = Bruch(27,6)

print a

a = gBruch(27,6)

print a

# python test.py

# 27 / 6

# 9 / 2

3.3.23

Page 25: Diskrete Modellierung - Wintersemester 2018/19 · Prinzip: Kapselung von Daten in Objekten ... x * y mul (self,other) Vektor-Produkt von x und y x.richtung() Einheitsvektor mit der

Zusammenfassung

Jede Programmiersprache bietet (andere) Moglichkeiten zum Entwurf von Datentypen.

Wir haben verschiedene Prinzipien gesehen, die stets beachtet werden sollten.

Beim Entwurf eines modularen Programms werden die Aufgaben,

die das Programm losen sollen, in Einzelteile zerlegt.

Beim Entwurf von Datentypen werden die Daten, mit denen das Programm arbeiten soll, und die

typische Benutzung der Daten zusammengesetzt.

Diese beiden unterschiedlichen Aufgaben mussen beim Programmieren zusammen gelost werden.

3.3.24