Seite 1 von 1

TypeError: 'NoneType' object is not subscriptable

Verfasst: Montag 23. August 2010, 23:38
von NilsV
eigentlich habe ich gehofft, das mir dieser Code das 1 mal 7 berechnet (Kopfrechnen ist halt zu anstrengend :wink: ):

Code: Alles auswählen

def berechnung(zahl):
    ergebnis = [zahl,]
    for zahlen in range(10): 
        zahl = ergebnis[0] + ergebnis[-1]
        ergebnis = ergebnis.append(zahl)
    return ergebnis

zahl = 7
ergebnis = berechnung(zahl)
print(ergebnis)
Aber leider bekomme ich nur diesen Fehler (Hab die Dateipfade rauseditiert):

Code: Alles auswählen

Traceback (most recent call last):
  File "problem.py", line 9, in <module>
    ergebnis = berechnung(zahl)
  File "problem.py", line 4, in berechnung
    zahl = ergebnis[0] + ergebnis[-1]
TypeError: 'NoneType' object is not subscriptable
Ich verstehe leider nicht was mir Python damit sagen möchte, was habe ich falsch gemacht? Ich verwende übrigends Python 3.1.2

Re: TypeError: 'NoneType' object is not subscriptable

Verfasst: Dienstag 24. August 2010, 00:01
von pudeldestodes
Die append-Methode verändert deine ergebnis-Liste in-place - und gibt das None-Objekt zurück, das du im 0-ten Durchlauf an ergebnis bindest. Im 1-ten Durchlauf der Schleife versuchst du dann eben mit [] nicht mehr auf ein Element einer Liste zuzugreifen, sondern auf ein Element des None-Objekt. Und das geht nicht, da None kein sequence type ist:

Code: Alles auswählen

>>> test = [1]
>>> test.append(2)
>>> test
[1, 2]
>>> return_value = test.append(3)
>>> return_value
>>> type(return_value)
<class 'NoneType'>
>>> return_value[0]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'NoneType' object is not subscriptable
>>> test
[1, 2, 3]

Kurz: ersetze

Code: Alles auswählen

ergebnis = ergebnis.append(zahl)
durch

Code: Alles auswählen

ergebnis.append(zahl)

Re: TypeError: 'NoneType' object is not subscriptable

Verfasst: Dienstag 24. August 2010, 00:13
von NilsV
Vielen Dank für Deine Hilfe. Ich erinnere mich das ich das Problem mit dem Rückgabewert von append schon mal hatte. Muss mir unbedingt merken das append nicht zusätzlich zugewiesen werden darf.

Re: [gelöst] TypeError: 'NoneType' object is not subscriptab

Verfasst: Dienstag 24. August 2010, 03:42
von BlackJack
@NilsV: Noch eine kleine Kritik am Quelltext: Er ist zu kompliziert. Das 1-mal `n` geht auch ganz einfach so:

Code: Alles auswählen

def calculate(n):
    return [i * n for i in xrange(1, 11)]
Auf jeden Fall würde ich bei Deinem Quelltext innerhalb der Funktion `zahl` nicht neu binden und anstelle von ``ergebnis[0]`` schreiben. Das ist eine unnötige Indirektion, wo sich der Leser erst klar darüber werden muss, dass da immer der gleiche Wert steht und welcher das ist.

Re: [gelöst] TypeError: 'NoneType' object is not subscriptab

Verfasst: Dienstag 24. August 2010, 05:02
von hendrikS
Oder:

Code: Alles auswählen

def calculate(n):
    return range(n,n*11,n)

Re: [gelöst] TypeError: 'NoneType' object is not subscriptab

Verfasst: Dienstag 24. August 2010, 05:16
von cofi
Wobei das bei Python3 nur einen Generator zurueckgibt. In BlackJack's Beispiel muss man dann auch `xrange` durch `range` ersetzen.

Zumindest hoffe ich, dass der OP Python3 benutzt, da er sonst das arme `print` missbraucht.

Re: TypeError: 'NoneType' object is not subscriptable

Verfasst: Dienstag 24. August 2010, 16:08
von NilsV
Zumindest hoffe ich, dass der OP Python3 benutzt, da er sonst das arme `print` missbraucht.
Python 3.1.2, also keine Missbrauchs Gefahr für print :wink: (vermutlich im Gegensatz zum Rest von Python, allerdings ohne Vorsatz :oops: )
@NilsV: Noch eine kleine Kritik am Quelltext: Er ist zu kompliziert.
Aus der Perspektive eines erfahrenen Python Programmierers mag das so sein, für mich als Anfänger ist es Quelltext den ich verstehe. Dein Beispiel (mit range anstelle von xrange) liefert zwar das selbe Ergebnis mit wesentlich weniger Quelltext, aber ich verstehe leider nicht was da steht:

Das i zum Beispiel, ich schreibe da bisher immer etwas hin das mir beim Lesen verständlich macht was die For Schleife tut, in meinem Beispiel so als währe das Wort Zahlen nichts weiter als eine art Kommentar. i wurde, nach meinem mangelnden Wissenstand, nirgendwo definiert, wie und wieso kann man damit Rechnen? Was ist i? Eine Art lokale Zuweisung die nach dem Schleifenende wieder Verschwindet (Begrenzte Haltbarkeit)? Was kann man i zuweisen?

Das einzige was für mich an dem Konkreten Beispiel Sinn ergeben würde(nachdem ich es 10 Minuten angestarrt habe) ist das i eine Art Platzhalter für die einzelnen Zahlen ist die Range liefert (wird wohl auch so sein), ich verstehe aber nicht die Logik im Syntax. Ich könnte das jetzt einfach abschreiben (und vermutlich auch auf andere Situationen übertragen) aber das wäre nur abschreiben, weil ich nicht verstehe was das geschriebene bedeutet (oder die Bedeutung nur erahnen/raten kann). Was es für mich am nächsten Tag schwierig macht zu verstehen, was ich da geschrieben habe.

Für eine Erklärung was es wirklich damit auf sich hat, wäre ich natürlich sehr dankbar.

Re: TypeError: 'NoneType' object is not subscriptable

Verfasst: Dienstag 24. August 2010, 16:21
von BlackJack
@NilsV: Das `i` ist die Schleifenvariable. Das kann man fast wörtlich lesen wie es da steht: `i` mal `n` für (jedes) `i` aus dem Bereich (range) von 1 bis 11 (exklusive). Das ``for``...``in`` steht halt nach dem Ausdruck der das einzelne Listenelement beschreibt, statt wie bei einer normalen ``for``-Schleife davor.

Ohne die "list comprehension" (LC) bräuchte man einen zusätzlichen Namen an den man die Ergebnisliste bindet. Das sähe dann so aus:

Code: Alles auswählen

def calculate(n):
    result = list()
    for i in xrange(1, 11):
        result.append(i * n)
    return result
Bei der LC braucht man den Namen für die Liste nicht mehr um ein einzelnes Element anzuhängen und der Ausdruck aus dem `append()` wandert an die erste Stelle in der LC.

Re: TypeError: 'NoneType' object is not subscriptable

Verfasst: Dienstag 24. August 2010, 16:21
von cofi
`i` ist nicht magisch, das Konstrukt nennt sich `List Comprehension` und i wird nach der "Benutzung" zugewiesen naemlich durch `for i in range(1,11)`.

Vielleicht kommt dir die mathematische Mengenschreibweise (Zermelo-Fraenkel) da bekannt vor: {i ∈ N : i ungerade}
Kann man in Python (mit Generator Expressions, dasselbe in gruen, allerdings noetig weil das eine "unendliche" Anzahl ist) mit

Code: Alles auswählen

(i for i in itertools.count(0) if i % 2 == 1)
schreiben. Und wie gesagt kann das `i` auch `zahl` heissen. Fuer Programmierer ist `i` nur eben _die_ Zaehlvariable.

Re: TypeError: 'NoneType' object is not subscriptable

Verfasst: Dienstag 24. August 2010, 16:52
von /me
NilsV hat geschrieben:Für eine Erklärung was es wirklich damit auf sich hat, wäre ich natürlich sehr dankbar.
Man kann den Code fast auf Deutsch übersetzen:

[i * n for i in xrange(1, 11)]
Eine Liste mit den Werten i*n für alle i im Bereich von 1 (inklusive) bis 11 (exklusive)