Seite 1 von 1
return-Anweisung gibt immer None zurück
Verfasst: Samstag 8. November 2008, 16:44
von ki
Hallo liebes Forum,
ich bin neu hier und habe gleich mal eine Frage zu meinem kleinen Script, das ich hier mal poste:
Code: Alles auswählen
f = ''
def factors(n, i):
global f
if i == 0:
print f
return f
elif n % i > 0:
factors(n, i-1)
else:
f = str(i) + " " + f
factors(n, i-1)
print factors( int( raw_input('N eingeben: ') ), int( raw_input('i eingeben: ') ) )
Also, Wenn ich z. B. für N und i jeweils 10 eingebe, komt folgende Meldung zurück:
N eingeben: 10
i eingeben: 10
1 2 5 10
None
Hat jemand eine Ahnung, wodran das liegen kann? Über print funktioniert die Rückgabe ja ...
Danke für Eure Hilfe!
Ki
Verfasst: Samstag 8. November 2008, 16:55
von numerix
In Python hat jede Funktion einen Rückgabewert. Wenn du nicht explizit via return einen Wert zurückgibst, dann ist es None.
In deinem Fall tritt das ein, wenn der "else"-Teil abgearbeitet wird und zu Ende ist.
Verfasst: Samstag 8. November 2008, 20:07
von ki
Hmm, aber er kann ja nicht nach dem else Teil raus, da dann die funktion factors erneut aufgerufen wird. Die rekursive Schleife wird ja nur bei der if == true Abfrage verlassen. Und hier gibt das Skript ja über den print-Befehl korrekt den Wert von f aus, allerdings wird über die return-Anweisung None zurückgegeben.
Das verstehe ich halt nicht
Verfasst: Samstag 8. November 2008, 20:12
von Pekh
Wenn eine Funktion nicht über ein explizites 'return' beendet wird ergänzt der Interpreter ein implizites 'return None'. Und das ist bei dir nach dem Abarbeiten des 'else'-Zweiges der Fall.
Edit: Und auch nach dem 'elif'. Einfach weil du das Ergebnis der rekursiven Aufrufe von factors nicht weiter hochreichst. Schreibe mal sowohl im 'elif'-Zweig als auch im 'else'-Teil ein 'return' vor den Funktionsaufruf. Das sollte dieses Problem beheben.
Edit2: Und warum gehst du über 'global', wenn du doch ohnehin schon mit Parametern arbeitest? Das schreit doch geradezu nach irgendwelchen unbeabsichtigten Seiteneffekten.
Verfasst: Samstag 8. November 2008, 20:24
von ki
Aber die funktion wird ja in der if Abfrage durch ein explizites return beendet
edit: sorry, habe erst danach deine edits gelesen
Verfasst: Samstag 8. November 2008, 20:34
von ki
wenn ich f nicht global setze, bekomme ich folgende Fehlermeldung:
f = str(i) + " " + f
UnboundLocalError: local variable 'f' referenced before assignment
Das ist nun mein aktueller Code:
Code: Alles auswählen
f = ''
def factors(n, i):
#global f
if i == 0:
return f
elif n % i > 0:
factors(n, i-1)
return f
else:
f = str(i) + " " + f
factors(n, i-1)
return f
print factors( int( raw_input('\nN eingeben: ') ), int( raw_input('i eingeben: ') ) )
Das Problem ist, wenn ich f nicht ausserhalb der funktion definiere, bekome ich die Meldung, das ich versuche eine unbekannte Variable in der Zuweisung zu verwenden.
Wenn ich aber f in jeder neuen Instanz von der Funktion mittels f = "" neu definiere, kann ich ja nicht meinen Ausgabe-String über die Instanzen zusammensetzen.
Hat jemand einen alternativen Vorschlag?
edit: ach ja, durch die returns ist nun das Problem gelöst, das None zurückgegeben wurde
Verfasst: Samstag 8. November 2008, 20:36
von Pekh
Der in meinen Augen schönere Ansatz ohne das allgemein verpönte 'global':
Code: Alles auswählen
def factors(n, i, f=''):
if i == 0:
print f
return f
elif n % i > 0:
return factors(n, i-1, f)
else:
return factors(n, i-1, f) + ' %d' % i
Verfasst: Samstag 8. November 2008, 20:52
von ki
Das ist allerdings schön!
Gefällt mir gut mit dem return die funktion erneut aufzurufen
Danke für die Hilfe!
Verfasst: Samstag 8. November 2008, 21:02
von DasIch
Du gibst mit return den Wert zurück, den die wiederaufgerufene Funktion zurückgibt. Wenn dir dass klar ist weisst du auch wieso du vorher None bekommen hast.
Verfasst: Montag 10. November 2008, 19:36
von yipyip
Das 'f' wird doch eigentlich gar nicht gebraucht.
Und eine Liste als Datenstruktur halte ich auch für sinnvoller.
Code: Alles auswählen
def factors(n, i):
if i <= 0:
return []
return factors(n, i-1) + ([], [i])[not n % i]
@ki
Dir schwebte (vermutlich etwas vage) das Konzept
eines Akkumulators vor Augen,
daher 2 Variationen zu diesem Thema:
Code: Alles auswählen
def factors2(n, i, acc=[]):
if i <= 0:
return acc
return factors2(n, i-1, (acc, acc + [i])[not n % i])
####
def factors3(n, i, acc=None):
if acc == None:
acc = []
if i <= 0:
return acc
if not n % i:
acc.append(i)
return factors3(n, i-1, acc)
yipyip