PRG-1 – Übung 05

Werbung
Martin Teufel
Matr.-Nr.: 3136289
Tutorin: Eva Reitz (G3; besuche G4)
PRG-1 – Übung 05
Aufgabe 1 – Aggregierte Datentypen & Klassen
a) Queue
# -*- coding: cp1252 -*# Queue-/Warteschlangen-Implemetierung in Python (FIFO)
class CQueue(object):
__Liste__=[]
def enqueue(self, einf_Objekt):
CQueue.__Liste__.insert(0,einf_Objekt)
print "aktuelle Queue:"
print CQueue.__Liste__
print
def dequeue(self):
if len(CQueue.__Liste__)==0:
print "None"
print
return None
else:
x=CQueue.__Liste__[len(CQueue.__Liste__)-1]
print "entfernt: ",x
del CQueue.__Liste__[len(CQueue.__Liste__)-1]
print "aktuelle Queue:"
if len(CQueue.__Liste__)!=0:
print CQueue.__Liste__
print
else:
print "None"
print
Queue=CQueue()
term=False
print "Queue-Implementierung"
print "---------------------"
print
while term==False:
print "Was möchten Sie tun?"
was_tun=raw_input ("Ein Objekt hinzunfügen (h), das Vorderste entfernen (e) oder beenden (b)?: ")
if was_tun == "h":
einf_Objekt=raw_input ("Bitte das einzufügenden Objekt eingeben: ")
try:
einf_Objekt=int(einf_Objekt)
except ValueError: pass
Queue.enqueue(einf_Objekt)
elif was_tun == "e":
Queue.dequeue()
elif was_tun == "b":
print
print "Programm beendet."
term=True
else: print "Falsche Eingabe!"
-1-
b) Stack
# -*- coding: cp1252 -*# Stack-Implemetierung in Python (LIFO; links entspricht unten, rechts entspricht oben)
import operator;
class CStack(object):
__Liste__=[]
def push(self, einf_Objekt):
Stack.__Liste__.append(einf_Objekt)
print "aktueller Stack:"
print CStack.__Liste__
print
def pop(self):
if len(Stack.__Liste__)==0:
print "None"
print
return None
else:
x=CStack.__Liste__[len(CStack.__Liste__)-1]
print "entfernt: ",x
del CStack.__Liste__[len(CStack.__Liste__)-1]
print "aktueller Stack:"
if len(CStack.__Liste__)!=0:
print CStack.__Liste__
print
else:
print "None"
print
Stack=CStack()
term=False
print "Stack-Implementierung"
print "---------------------"
print
while term==False:
print "Was möchten Sie tun?"
was_tun=raw_input ("Ein Objekt hinzunfügen (h), das Oberste entfernen (e) oder beenden (b)?: ")
if was_tun == "h":
einf_Objekt=raw_input ("Bitte das hinzuzufügenden Objekt eingeben: ")
try:
einf_Objekt=int(einf_Objekt)
except ValueError: pass
Stack.push(einf_Objekt)
elif was_tun == "e":
Stack.pop()
elif was_tun == "b":
print
print "Programm beendet."
term=True
else: print "Falsche Eingabe!"
-2-
Aufgabe 2 – Parameter und Objektmanagement
a) call by value / call by reference
Unter “call by value” beim Aufruf einer Prozedur oder Funktion versteht man die Übergabe des
Wertes einer Variable, d.h. hierbei wird eine Kopie des Wertes der Prozedur- oder
Funktionsvariable zugewiesen. Anders bei „call by reference“: Hier wird nur die
Speicheradresse übergeben, d.h. Prozedur- oder Funktionsvariable verweist lediglich auf die
Ausgangsvariable (=Referenz). Dadurch wird (evtl. unnötig belegter) Speicherplatz eingespart.
Aus diesem Unterschied folgt aber auch: Wird in der Prozedur oder Funktion der Wert
geändert, ändert sich dieser bei „call by reference“ auch in der Ausgangsvariable, bei „call by
value“ hingegen nicht, da ja nur die Kopie geändert wird.
b) Kopieren von Objekten
Es gibt zwei Möglichkeiten, Objekte zu kopieren:
Prinzipiell kopiert man Objekte mit Hilfe des Moduls „copy“, bzw. dessen Methoden, deren es
wie schon erwähnt Zwei an der Zahl gibt. Das sieht dann z.B. wie folgt aus:
import copy
[...]
p2 = copy.copy(p1)
Dieses normale oder „flache“ Kopieren funktioniert (wie ersichtlich ist) mit der gleichnamigen
Methode „copy“ (copy.copy(Objekt)). Dadurch wird nur das Objekt selber kopiert, und nichts
weiter.
Des weiteren gibt es aber noch das „tiefe“ Kopieren (deepcopy). Diese Methode kopiert nicht
nur das Objekt selbst, sondern auch noch alle „darunter liegenden“/eingebetteten Objekte, so
daß das Objekt vollständig, also quasi mit allem, was dazu gehört kopiert wird (vergleiche del
und deltree bei MS-DOS). Das ganze sieht dann z.B. so aus:
import copy
[...]
p2 = copy.deepcopy(p1)
Ein Unterschied ist z.B. auch der, daß bei Änderungen an einem eingebetteten Objekt beim
„flachen Kopieren“ sich die Änderungen auf beide „Elterobjekte“ auswirken, beim „tiefen
Kopieren“ eben nicht, da dabei beides völlig voneinander getrennte Objekte sind.
Aufgabe 3 – Rekursion
a) Testprogramm zur Rekursionstiefe
Nach der erreichen des Rekursionslimits resp. der maximalen Rekursionstiefe (standardmäßig
1000) bricht der Interpreter die Ausführung des Algorithmus’ ab (bei mir komischerweise
schon bei 979 bzw. immer exakt 21 Rekursionen früher) und gibt nur noch Fehlermeldungen
aus, bis schließlich (zumindest bei mir) der gesamte Prozeß terminiert.
Die Festlegung der maximalen Rekursionstiefe beugt unendlicher Rekursion vor, und hilft
einen Stack-Überlauf zu verhindern, was zum Absturz von Python führen könnte/würde (was
bei mir seltsamer Weise aber trotzdem aufgrund der anhaltenden Ausgabe von Fehlermeldungen geschieht).
b) Rekursionstiefe festlegen
Mit dem Befehl bzw. der sys-Methode „setrecursionlimit“ kann man durch
sys.setrecursionlimit(Limit) die maximale Rekursionstiefe festlegen, was wie bereits
beschreiben einen Stack-Überlauf verhindert bzw. verhindern soll.
Das höchstmögliche Limit ist dabei Plattform-abhängig.
→ siehe hierzu auch mein selbstgeschriebenes Testprogramm „Rekursionslimit festlegen und
ausgeben“
c) & d)
→ siehe Abgabe von Susanne Lipp (G4)
-3-
Rekursionsbaum zu d)
-4-
Herunterladen