Funktionen und Variable (war: "Schleife")

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
merlin_emrys
User
Beiträge: 110
Registriert: Freitag 3. März 2006, 09:47

@ Rebecca und BlackJack: Noch ein ganz warmes Dankeschoen!
Rebecca hat geschrieben:Du meinst Funktionen. Ein Modul ist etwas, was in einer eigenen Datei steht und dann mit import importiert wird.
Das heisst, wenn ich meine Funktionen in eine eigene Datei stecke und von dort zu Beginn per import hole, werden sie zu Modulen? Oder ist das Modul dann die gesamte Datei?
Rebecca hat geschrieben:
merlin_emrys hat geschrieben:Aber was meint der zweite Teil des Satzes? Dass ich, wie im vorigen Absatz, "done" als etwas definiere, was die Funktion entgegennimmt und hinterher wieder ausgibt?
Genau das. Dafuer gibt's return;
Danke fuer den Tip, allerdings laesst er mich doch noch ein wenig ratlos. Das, was return hier tut, entspricht erstmal dem, was ich von einem print auch erwarten wuerde. Mein Buch sagt mir leider auch nicht viel dazu... Koenntest Du dazu noch ein Wort verlieren? Ich vermute mal, man kann return irgendwie dazu verwenden, sich Werte auch fuer andere Zwecke (also nicht nur analog zu print) zu holen? Ich habe es mal mit Deinem Beispielprogramm und dann

Code: Alles auswählen

liste = []
liste.append(addieren(4,5))
versucht und festgestellt, dass es einen Unterschied macht, wenn ich die return-Zeile weglasse... ist das also ungefaehr die gedachte Verwendung?

BlackJack hat geschrieben:
... braucht also der Generator immer eine Schleife, in der er steht?
Braucht er nicht, man kann auch die `next()` Methode benutzen um die Werte zu bekommen.
Die `next()` Methode hast Du weiter oben auch schon erwaehnt, aber mein Buch hat sie zumindest im Index nicht aufgefuehrt... Darf ich noch eine Runde weiter dumme Fragen stellen und mich erkundigen, was das fuer eine Methode ist?
BlackJack hat geschrieben:Tupel können nicht verändert werden. Du kannst also nicht ``t[x] = y`` ausführen. Und es gibt weniger Methoden als auf Listen. Wenn Du lieber Listen von der Funktion haben möchtest, dann kannst Du einfach anstelle des `tuple()` ein `list()` benutzen.
Ah, das ist prima! :-)
BlackJack hat geschrieben:Wenn Du `evaluate()` in die Funktion einbaust, dann spezialisierst Du damit die Funktion stärker. Wenn beides getrennt bleibt, dann kannst Du die Zahlen mit verschiedenen Auswertungsfunktionen benutzen und auch verschiedene Funktionen zum Generieren der Zahlen verwenden.
Das heisst, die Methode, die Funktionen getrennt zu halten, ist vor allem flexibler? Sie scheint mir auch besser zu "lesen", weil besser erkennbar, dass da ein neuer "Block" anfaengt. Wenn es fuer das Ausfuehren des Programms keinen Unterschied macht, werde ich dann die zweite Version nehmen.
BlackJack

merlin_emrys hat geschrieben:@ Rebecca und BlackJack: Noch ein ganz warmes Dankeschoen!
Rebecca hat geschrieben:Du meinst Funktionen. Ein Modul ist etwas, was in einer eigenen Datei steht und dann mit import importiert wird.
Das heisst, wenn ich meine Funktionen in eine eigene Datei stecke und von dort zu Beginn per import hole, werden sie zu Modulen? Oder ist das Modul dann die gesamte Datei?
Alles was in einer *.py Datei steht bildet zusammen ein Modul und kann von anderen Modulen aus oder im interaktiven Interpretierer importiert werden.
Danke fuer den Tip, allerdings laesst er mich doch noch ein wenig ratlos. Das, was return hier tut, entspricht erstmal dem, was ich von einem print auch erwarten wuerde. Mein Buch sagt mir leider auch nicht viel dazu... Koenntest Du dazu noch ein Wort verlieren? Ich vermute mal, man kann return irgendwie dazu verwenden, sich Werte auch fuer andere Zwecke (also nicht nur analog zu print) zu holen? Ich habe es mal mit Deinem Beispielprogramm und dann

Code: Alles auswählen

liste = []
liste.append(addieren(4,5))
versucht und festgestellt, dass es einen Unterschied macht, wenn ich die return-Zeile weglasse... ist das also ungefaehr die gedachte Verwendung?
Mit ``return`` gibt man an, was eine Funktion zurückgibt. Man kann sich auch vorstellen, das bei der Ausführung der Aufruf der Funktion durch den Rückgabewert ersetzt wird. Genau wie in der Mathematik. Bei Deinem Listenbeispiel wird ``addieren(4,5)`` ausgegeführt und durch das was ``return`` zurückgibt ersetzt. Und diese 9 wird dann an die Liste angehängt.

In Python hat jede Funktion einen Rückgabewert, wenn man selbst keinen festlegt, dann wird `None` zurückgegeben. Das wirst Du sicher in der Liste gesehen haben, wenn Du aus dem ``return`` ein ``print`` gemacht hast.
BlackJack hat geschrieben:
... braucht also der Generator immer eine Schleife, in der er steht?
Braucht er nicht, man kann auch die `next()` Methode benutzen um die Werte zu bekommen.
Die `next()` Methode hast Du weiter oben auch schon erwaehnt, aber mein Buch hat sie zumindest im Index nicht aufgefuehrt... Darf ich noch eine Runde weiter dumme Fragen stellen und mich erkundigen, was das fuer eine Methode ist?
Die sollte im Zusammenhang mit Iteratoren erwähnt werden. In der Python-Doku werden sie Zusammenhänge hier erklärt:

http://docs.python.org/lib/typeiter.html
Benutzeravatar
Michael Schneider
User
Beiträge: 569
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Brandenburg

Hi Merlin!
merlin_emrys hat geschrieben:
Michael Schneider hat geschrieben:ist zwar wahrscheinlich Off-Topic, aber ich finde "Das Python-Buch" einfach genial für Einsteiger!
Hast Du dazu noch mehr Angaben? "Phyton-Buch" gibt bei der Amazon-Schnellsuche keinen Treffer :-( ... Allerdings komme ich ohnehin an deutsche Literatur hier (in Japan) nur sehr schwer, und die Versandkosten verringern den Spass zusaetzlich.
Amazon: http://www.amazon.de/gp/product/3827311 ... y&v=glance
Ist eben ein deutsches Buch und bei .com wahrscheinlich nicht erhältlich. Und wegen dem schicken - mal sehen, ob ich diese Woche noch eine Lieferung nach Japan habe... nein, leider nicht. ;-)
merlin_emrys hat geschrieben:
Michael Schneider hat geschrieben:also die Kombinationen würde ich wie bei Binärzahlen berechnen: ...

Wenn man die mit zip kombiniert, erhält man alle Kombinationen. Wo war doch gleich das Problem? :)
Ich glaube, das Problem ist im Thread-Titel mit "Anfaengerproblem" angedeutet... Und "Anfaenger" heisst in diesem Fall, dass ich spaetestens beim ersten Auftreten von "lamda" so meine Zweifel bekomme, ob es nicht den Rahmen des Forums sprengt, um Erklaerungen zu bitten, was es damit auf sich hat...
Lambda Ausdrücke generieren Funktionen ohne def-Anweisung. Das ist nützlich, wenn man sie direkt als Parameter übergeben möchte.

Allgemeine Syntax:
lambda arg1, arg2[, ...] : Ausdruck
Ich verwendete:
lambda x, y: x+y
Was soviel bedeutet wie: "Erzeuge eine Funktion, die zwei Werte erwartet und dann die Summe dieser zurückgibt." Bei Listen bedeutet das, dass beide Listen zu einer großen zusammengefügt werden.

Die reduce-Funktion erwartet als erstes Argument ein Funktionsobjekt und als zweites Argument ein iterierbares Objekt, z.B. eine Liste [1, 2, 3, 4]. Dann wendet sie die übergebene Funktion erst auf die ersten beiden Elemente an, dann auf deren Ergebnis und das dritte Element usw. bis es nur noch einen Wert gibt, der zurückgegeben wird.
Also:
a) 1+2
b) (3)+3
c) (6)+4
-> Rückgabewert 10

Zugegeben, man koennte den Code meines Vorschlags noch etwas strecken. Aber ihn mit Perl zu vergleichen ist eine Beleidigung. Ich wollte nur mal eine Alternative zum üblicherweise verwendeten divmod aufzeigen. ;-)

Grüße,
Michael
Diese Nachricht zersört sich in 5 Sekunden selbst ...
merlin_emrys
User
Beiträge: 110
Registriert: Freitag 3. März 2006, 09:47

Zuerst zwei kleine Dinge am Rande:

Das erste:
Michael Schneider hat geschrieben:Ist eben ein deutsches Buch und bei .com wahrscheinlich nicht erhältlich. Und wegen dem schicken - mal sehen, ob ich diese Woche noch eine Lieferung nach Japan habe... nein, leider nicht. ;-)
Uebernaechste Woche waere schon auch noch ok... :-) Nein, im Ernst: Vielen Dank. Ich habe das Buch auf meine Liste zu besorgender Buecher gesetzt und hoffe mal, wenn ich naechstes Jahr wieder in Deutschland bin, noch ein Exemplar auftreiben zu koennen. Danke fuer den Tip, und auch danke fuer die Erklaerung der lambda-Funktion :-) .

Das zweite: Das Problem war (und ist) offenbar mein Umgang mit den Variablen - sollte ich das Thema ("Aus selbstgebauter Schleife entkommen") entsprechend umbenennen ("Globale und lokale Variablen")?

Mit den Variablen habe ich naemlich wohl schon wieder das naechste Problem... Ich habe den Zaehler in das gesamte Programm eingebaut, aber in dem ist "evaluate" mehr als nur eine "print"-Funktion. Sie rechnet und vergleicht einige Dinge - ich habe den Code unten angehaengt; "evaluate" geht derzeit von Zeile 24 bis Zeile 99. Wenn ich richtig gezaehlt habe, tauchen da mindestens 14 Variable auf (im Grunde die Zeilen 26 bis 39), und ein paar von denen brauche ich spaeter noch zum weiteren Auswerten.
Urspruenglich waren die Variablen-Definitionen im "allgemeinen" Teil (vor Zeile 190) untergebracht, aber dann haette ich sie alle als Parameter an die "evaluate"-Funktion uebergeben muessen, und das waere eine ziemlich lange Liste. Eventuell komme ich aber doch nicht umhin; jetzt komme ich naemlich an die Werte nicht dran, wenn ich meine Auswertung weiterfuehren will.
Oder hilft mir da "return" weiter? Ich habe es, weil sich die erste auftauchende Fehlermeldung derzeit ueber "fallzahl" in Zeile 212 beschwert, erstmal mit "fallz = return fallzahl" (als Zeile 99, jetzt mit #)versucht und in Zeile 212 entsprechend "fallzahl" durch "fallz" ersetzt, das hat aber jedenfalls nicht funktioniert.

Hier das Programm, wie es derzeit aussieht; und falls sich jemand über völlig sinnlose else-Anweisungen wundert: Die sind noch Reste meines Misstrauens, ob sich nicht manchmal doch unmoegliche Zustaende einstellen...

Code: Alles auswählen

# Programmentwurf

#
# Zaehlschleife
#
def counter(gro):
    aktuList = [1] * len(gro)
    last_index = len(gro) - 1
    while True:
        yield list(aktuList)
        i = last_index
        aktuList[i] += 1
        while aktuList[i] > gro[i]:
            aktuList[i] = 1
            i -= 1
            if i < 0:
                raise StopIteration()
            aktuList[i] += 1

#
# Einzelauswertung der Werte
#
#
def evaluate(aktuList,gro,bezl,konto,begausw):
    if begausw == "ja":
        gel = 0
        ausgegl = 0
        miss = 0
        fallzahl = 0
        summenliste = []
        fehlbetrag = 0
        fehlbetragliste = []
        kontonutzung = 0
        kontonutzliste = []
        ueberschuss = 0
        ueberschussliste = []
        treffer = 0
        trefferliste = []
        geprueft = []
    else:
        pass
    nochgel = 1
    for i in range(0,len(aktuList)-1):
        if aktuList[i] > bezl[i]:
            ueberschuss = ueberschuss + (bezl[i]-aktuList[i])
        elif aktuList[i] == bezl[i]:
            pass
        else:
            diff = aktuList[i]-bezl[i]
            if konto == []:
                nochgel = 0
                fehlbetrag = fehlbetrag - diff
            else:
                if len(konto) == 1:
                    konto[0] = konto[0] - diff
                    if konto[0] >= 0:
                        pass
                    else:
                        nochgel = 0
                        fehlbetrag = fehlbetrag - diff
                else:
                    if konto[i] >= aktuList[i]-bezl[i]:
                        kontonutzung = kontonutzung + diff
                    else:
                        nochgel = 0
                        fehlbetrag = fehlbetrag - diff
    if nochgel == 1:
        gel = gel + 1
        if ueberschuss > 0:
            ueberschussliste.append(aktuList)
            ueberschussliste.append(ueberschuss)
        else:
            treffer = treffer + 1
            trefferliste.append(aktuList)
    else:
        if fehlbetrag == 0:
            fehlbetragliste.append(aktuList)
            fehlbetragliste.append([0])
            # die innere Liste ist Fehlerindikator: Fehlbetrag 0 ist geschafft
        elif fehlbetrag < 0:
            fehlbetragliste.append(aktuList)
            if konto == []:
                fehlbetragliste.append(aktuList)
                fehlbetragliste.append(fehlbetrag)
                # der Eintrag ist für kein Konto und gem. Konto ist identisch
            elif len(konto) == 1:
                fehlbetragliste.append(aktuList)
                fehlbetragliste.append(fehlbetrag)
            else:
                fehlbetragliste.append(aktuList)
                fehlbetragliste.append(konto)
        else:
            fehlbetragliste.append(aktuList)
            fehlbetragliste.append([])
            # die innere Liste ist Fehlerindikator: Fehlbetrag > 0 ist unzulaessig
    begausw = "nein"
    fallzahl = fallzahl + 1
    geprueft.append(aktuList)
#    fallz = return(fallzahl)


#
# Eingabe und Definition der Anfangswerte
#
#
print "Werte festlegen:"
#
# Maximalwertabfrage:
#
f = False
groabfr = raw_input("Alle Maximalwerte gleich gross? j_a, n_ein: ")
while f == False:
    try:
        if groabfr == "j":
            ff = False
            while ff == False:
                try:
                    anz = int(raw_input("Anzahl der Werte eingeben: "))
                    ff = True
                except ValueError:
                   print "Keine gültige Eingabe, nochmal bitte: "
            gro = [int(raw_input("Maximalwert angeben: "))] * anz
            f = True
        elif groabfr == "n":
            i = 1
            gro = []
            while i > 0:
                i = int(raw_input("Naechster Maximalwert, 0 zum Abbruch: "))
                gro.append(i)
            if gro == [0]:
                print "So geht das nicht, ein Wert muss schon sein..."
            else:
                f = True
        else:
            f = False
    except ValueError:
        print "Keine gültige Eingabe, nochmal bitte: "

#
# Bezugswertabfrage:
#
f = False
bezabfr = raw_input("Bezugswert e_inheitlich oder s_pezifisch? e/s: ")
banz = len(gro)
while f == False:
    try:
        if bezabfr == "e":
            bezl = [int(raw_input("Gib den Bezugswert an: "))] * banz
            f = True
        elif bezabfr == "s":
            bezl = [0] * banz
            for i in range(banz):
                bezl[i] = int(raw_input("Naechsten Bezugswert angeben: "))
            f = True
        else:
            f = False
    except ValueError:
        print "Keine gültige Eingabe, nochmal bitte: "

#
# Kontoabfrage:
#
f = False
kanz = len(gro)
while f == False:
    try:
        kontoabfr = raw_input("Gibt es ein Konto? j_a,n_ein: ")
        if kontoabfr == "n": 
                konto = []          
                f = True
        elif kontoabfr == "j":
                konto = [0]
                kontodef = raw_input("Ge_m_einsames oder ge_t_renntes Konto? m/t: ")
                if kontodef == "m":
                    konto = [int(raw_input("Kontogröße angeben: "))]
                    f = True
                elif kontodef == "t":
                    konto = [0] * kanz
                    for i in range(kanz):
                        konto[i] = int(raw_input("Naechsten Kontowert angeben: "))            
                    f = True
                else: 
                    f = False
        else: 
                print "Keine gültige Eingabe"
    except ValueError:
        print "Keine gültige Eingabe, nochmal bitte: "


# 
# Kontrolle: Werte ausgeben:
#
print "Folgende Werte werden verwendet:"
print "Maxima: ", gro
print "Bezugswerte: ", bezl
print "Kontowerte: ", konto

#
# Zaehlschleife und Pruefung aufrufen:
#
begausw = "ja"
for aktuList in counter(gro):
    evaluate(aktuList,gro,bezl,konto,begausw)

#
# Abschliessende Pruefung der Fallzahl (tfz = theoretische Fallzahl)
#
tfz = gro[0]    
for i in range(1,len(gro)):
    tfz = tfz*gro[i]
    i = i + 1
if fallzahl == tfz:
    print "Auswertung erfolgreich"
else:
    print "Theoretische Fallzahl und Zahl gepruefter Faelle stimmen nicht ueberein."
 
#
# Ausgabe
#
if anz == 0:
    print "Irgendwas ist da schiefgegangen, bitte um Entschuldigung..."
else:
    print "Die Zahl der misslungenen Faelle ist ", miss
    print "Die Zahl der gelungenen Faelle ist ", ausgegl + gel
    print "Von den gelungenen Faellen mussten ", ausgegl, " mithilfe des Kontos ausgeglichen werden"
    vollstausg = raw_input("Listen ausgeben? j_a, n_ein: ")
    if vollstausg == "j":
        print "Liste der geprueften Faelle: ", geprueft
        print "Liste der Fehlbetraege: ", fehlbetragliste
        print "Liste der Kontonutzungen: ", kontonutzungliste
        print "Liste der Ueberschuesse: ", ueberschussliste
    elif vollstausg == "n":
        print "ok"
    else:
        print "Keine gültige Eingabe"
bb1898
User
Beiträge: 199
Registriert: Mittwoch 12. Juli 2006, 14:28

merlin_emrys hat geschrieben: Das zweite: Das Problem war (und ist) offenbar mein Umgang mit den Variablen - sollte ich das Thema ("Aus selbstgebauter Schleife entkommen") entsprechend umbenennen ("Globale und lokale Variablen")?
Ich denke eher, Dein Problem ist der Umgang mit Funktionen, ihren Parametern und Rückgabewerten; deswegen habe ich die Überschrift mal so formuliert.

Ich muss gestehen, dass ich nicht versucht habe, Dein Programm zu verstehen - es ist zu lang, und für Leser, die das zugrundeliegende Problem nicht kennen, wären mehr Kommentare ganz dringend nötig.

Im übrigen gilt generell: der Versuch, ein Problem auf ein kurzes Programm zu reduzieren, bringt Dir nicht nur mehr Helfer, sondern oft schon die Lösung. Gerade am Anfang ist es absolut keine vergeudete Zeit, haufenweise Mini-Skripte zu schreiben, um eine Sache nach der anderen zu verstehen.
Mit den Variablen habe ich naemlich wohl schon wieder das naechste Problem... Ich habe den Zaehler in das gesamte Programm eingebaut, aber in dem ist "evaluate" mehr als nur eine "print"-Funktion. Sie rechnet und vergleicht einige Dinge - ich habe den Code unten angehaengt; "evaluate" geht derzeit von Zeile 24 bis Zeile 99. Wenn ich richtig gezaehlt habe, tauchen da mindestens 14 Variable auf (im Grunde die Zeilen 26 bis 39), und ein paar von denen brauche ich spaeter noch zum weiteren Auswerten.
Urspruenglich waren die Variablen-Definitionen im "allgemeinen" Teil (vor Zeile 190) untergebracht, aber dann haette ich sie alle als Parameter an die "evaluate"-Funktion uebergeben muessen, und das waere eine ziemlich lange Liste. Eventuell komme ich aber doch nicht umhin; jetzt komme ich naemlich an die Werte nicht dran, wenn ich meine Auswertung weiterfuehren will.
Oder hilft mir da "return" weiter? Ich habe es, weil sich die erste auftauchende Fehlermeldung derzeit ueber "fallzahl" in Zeile 212 beschwert, erstmal mit "fallz = return fallzahl" (als Zeile 99, jetzt mit #)versucht und in Zeile 212 entsprechend "fallzahl" durch "fallz" ersetzt, das hat aber jedenfalls nicht funktioniert.
Also ein paar allgemeine Bemerkungen zu Funktionen, ihren Parametern und ihren Rückgabewerten. Lutz & Ascher sagen es besser, aber das soll uns jetzt mal nicht stören.

Eine Funktion kann Werte von außen bekommen (als Parameter, in Klammern hinter dem Funktionsaufruf), oder in ihrem Inneren können Variable neu definiert werden. Egal, was sie damit anfängt, der Rest des Programms bekommt davon nur in zwei Fällen etwas mit:

- es ist ein Parameter von einem veränderlichen Datentyp (wichtigste Beispiele: Liste, Dictionary, selbst definierte Klasse; Gegenbeispiele: Zahlen, Strings, Tupel). Dann hat dieser Parameter nach dem Funktionsaufruf einen neuen Wert.

- der Wert wird mit "return <Ausdruck>" zurückgegeben. Dabei kann <Ausdruck> auch ein Tupel sein, auf diese Weise können mehrere Werte auf einmal zurückgegeben werden. Damit der Wert an anderer Stelle tatsächlich benutzt werden kann, muss der Funktionsaufruf entsprechend aussehen, im einfachsten Fall so:

meinNeuerWert = meineFunktion(meinEingabeparameter1, ...)

Jetzt hat meinNeuerWert den Wert, den meineFunktion ausgerechnet und zurückgegeben hat.

Ein "meinNeuerWert = return Ausdruck" in der Funktionsdefinition ist ein Syntaxfehler. return ist ja nicht selbst eine Funktion, sondern eine Anweisung.

Ich höre hier mal auf und warte besser auf Deine Rückfragen.
merlin_emrys
User
Beiträge: 110
Registriert: Freitag 3. März 2006, 09:47

bb1898 hat geschrieben: Im übrigen gilt generell: der Versuch, ein Problem auf ein kurzes Programm zu reduzieren, bringt Dir nicht nur mehr Helfer, sondern oft schon die Lösung. Gerade am Anfang ist es absolut keine vergeudete Zeit, haufenweise Mini-Skripte zu schreiben, um eine Sache nach der anderen zu verstehen.
An sich habe ich das versucht. Das Problem mit den Parametern ist mir aber erst begegnet, als ich einige Mini-Skripte kombiniert habe - vorher ist es nicht aufgetreten, weil ich meine Variablen jeweils eingeben oder fest vorgeben konnte, aber sie nicht von einem Teil in den andern schicken musste.
Eine Funktion kann Werte von außen bekommen (als Parameter, in Klammern hinter dem Funktionsaufruf), oder in ihrem Inneren können Variable neu definiert werden. Egal, was sie damit anfängt, der Rest des Programms bekommt davon nur in zwei Fällen etwas mit:

- es ist ein Parameter von einem veränderlichen Datentyp (wichtigste Beispiele: Liste, Dictionary, selbst definierte Klasse; Gegenbeispiele: Zahlen, Strings, Tupel). Dann hat dieser Parameter nach dem Funktionsaufruf einen neuen Wert.
Danke, das ist schon wichtig zu wissen... Ich haette nicht erwartet, dass sich Listen einerseits und Strings und Tupel andererseits an dieser Stelle unterschiedlich verhalten.
Ich hatte heute nacht erwogen, die lange Parameterliste irgendwie in einen einzigen "Zwischenspeicher" zu packen und diesen dann am Anfang von "evaluate" wieder zu "entpacken". Offenbar macht es dabei dann einen Unterschied, ob ich sie zu einer Liste mache (was gehen muesste, wenn ich nur Zahlen und Listen habe), oder ob ich daraus ein Tupel mache. Im ersten Fall muesste das Programm nach Abschluss des "evaluate"-Teils bei Verwendung einer Liste als "Zwischenspeicher" die neuen Werte direkt weiterverwenden, waehrend ich, wenn ich daraus einen Tupel gemacht habe, diesen am Ende von "evaluate" per return mit den geaenderten Werten fuellen muesste?

In "Pseudocode" umgesetzt: Im "Hauptprogramm":

Code: Alles auswählen

 # Dateneingabe usw.

param1 = 0
param2 = []
param3 = [1,1,1]

Zwischenspeicher = [param1,param2,param3]
evaluate(aktuList,gro,Zwischenspeicher) 
und zu Beginn von "evaluate":

Code: Alles auswählen

def evaluate(aktuList,gro,Zwischenspeicher):
   param1 = Zwischenspeicher[1]
   param2 = Zwischenspeicher[2]
   param3 = Zwischenspeicher[3]
   ... 
Das ist der Fall mit einer Liste. In dem Fall koennte ich fuer die Auswertung nach Ende von "evaluate" direkt auf die geaenderten param1, param2 und param3 zugreifen.
Aber wenn ich fuer "Zwischenspeicher" runde Klammern nehme, wird daraus ein Tupel. Und das verhaelt sich anders...
- der Wert wird mit "return <Ausdruck>" zurückgegeben. Dabei kann <Ausdruck> auch ein Tupel sein, auf diese Weise können mehrere Werte auf einmal zurückgegeben werden. Damit der Wert an anderer Stelle tatsächlich benutzt werden kann, muss der Funktionsaufruf entsprechend aussehen, im einfachsten Fall so:

meinNeuerWert = meineFunktion(meinEingabeparameter1, ...)

Jetzt hat meinNeuerWert den Wert, den meineFunktion ausgerechnet und zurückgegeben hat.
Der Teil ist mir jetzt noch nicht so klar. Versuchsweise wuerde ich in meinen "Pseudocode" so etwas einbauen:

Code: Alles auswählen

 def evaluate(aktuList,gro,Zwischenspeicher):
   ...
   # viel code
   ...
   Zwischenspeicher = (param1,param2,param3)
   return Zwischenspeicher 
Dann muessten fuer die weitere Auswertung die geaenderten Werte zur Verfuegung stehen.
Ganz gluecklich bin ich mit dieser Version noch nicht, weil der "Zwischenspeicher" bei hohen Eingabewerten am Ende von "evaluate" doch ziemlich umfangreich wird. Im Moment habe ich die Variablen erstmal nach "brauche ich spaeter noch" und "brauche ich nur innerhalb von evaluate" sortiert und festgestellt, dass ich 5 wohl nur "lokal" innerhalb von evaluate brauche. 9 bleiben damit, die evaluate veraendern soll, und wenn ich die als lange Liste uebergebe, funktioniert es zumindest schonmal fuer die Listen.

Wenn es irgendwen interessiert, kann ich auch nochmal eine genauer kommentierte Version des Programms abliefern...
bb1898
User
Beiträge: 199
Registriert: Mittwoch 12. Juli 2006, 14:28

merlin_emrys hat geschrieben:
- es ist ein Parameter von einem veränderlichen Datentyp (wichtigste Beispiele: Liste, Dictionary, selbst definierte Klasse; Gegenbeispiele: Zahlen, Strings, Tupel). Dann hat dieser Parameter nach dem Funktionsaufruf einen neuen Wert.
Danke, das ist schon wichtig zu wissen... Ich haette nicht erwartet, dass sich Listen einerseits und Strings und Tupel andererseits an dieser Stelle unterschiedlich verhalten.
Das ist gerade einer der wesentlichen Unterschiede zwischen Tupeln und Listen.
In "Pseudocode" umgesetzt: Im "Hauptprogramm":

Code: Alles auswählen

 # Dateneingabe usw.

param1 = 0
param2 = []
param3 = [1,1,1]

Zwischenspeicher = [param1,param2,param3]
evaluate(aktuList,gro,Zwischenspeicher) 
und zu Beginn von "evaluate":

Code: Alles auswählen

def evaluate(aktuList,gro,Zwischenspeicher):
   param1 = Zwischenspeicher[1]
   param2 = Zwischenspeicher[2]
   param3 = Zwischenspeicher[3]
   ... 
Das ist der Fall mit einer Liste. In dem Fall koennte ich fuer die Auswertung nach Ende von "evaluate" direkt auf die geaenderten param1, param2 und param3 zugreifen.
Nicht ganz. Auf geänderte param1, param2, param3 kannst Du nicht zugreifen. Auf geänderte Zwischenspeicher dagegen schon. Die Bindung der Namen param1, param2, param3 an die Elemente von Zwischenspeicher überlebt das Funktionsende nicht. Und wenn Du param1 änderst, aber danach nicht den neuen Wert explizit dem passenden Listenelement zuweist, dann geht es wieder nicht.

Das ist aber alles im Lehrbuch besser erklärt (Stichwort mutable / immutable values). Und übrigens, die diversen Links zu deutschsprachigen Tutorials im entsprechenden Teil dieses Forums hast Du gefunden?

Der Teil ist mir jetzt noch nicht so klar. Versuchsweise wuerde ich in meinen "Pseudocode" so etwas einbauen:

Code: Alles auswählen

 def evaluate(aktuList,gro,Zwischenspeicher):
   ...
   # viel code
   ...
   Zwischenspeicher = (param1,param2,param3)
   return Zwischenspeicher 
Dann muessten fuer die weitere Auswertung die geaenderten Werte zur Verfuegung stehen.
Richtig. Vorausgesetzt, Du rufst die Funktion richtig auf:

Code: Alles auswählen

Zwischenspeicher = evaluate(aktuList, gro, Zwischenspeicher) 
(die Namen können auch andere sein!)

Dagegen ist die Zuweisung vor dem return nicht wirklich nötig, Du kannst statt dessen einfach

Code: Alles auswählen

return (param1, param2, param3)
schreiben.
Ganz gluecklich bin ich mit dieser Version noch nicht, weil der "Zwischenspeicher" bei hohen Eingabewerten am Ende von "evaluate" doch ziemlich umfangreich wird. Im Moment habe ich die Variablen erstmal nach "brauche ich spaeter noch" und "brauche ich nur innerhalb von evaluate" sortiert und festgestellt, dass ich 5 wohl nur "lokal" innerhalb von evaluate brauche. 9 bleiben damit, die evaluate veraendern soll, und wenn ich die als lange Liste uebergebe, funktioniert es zumindest schonmal fuer die Listen.
Bequemer als eine lange Liste ist m.E. ein Dictionary: dann kannst Du Deine Variablennamen als Schlüssel nehmen und musst nicht auf die Indizes innerhalb der Liste aufpassen. Oder gleich eine selbstdefinierte Klasse. Für beides gilt: wahrscheinlich erst mal ungewohnt, aber die investierte Lernzeit lohnt sich.
Antworten