TypeError: 'int' object is not subscriptable

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.
Antworten
schweden1997
User
Beiträge: 3
Registriert: Samstag 1. September 2012, 21:17

Hallo;
wenn ich mein Programm starte funktioniert noch alles wie es soll.

Code: Alles auswählen

def convert():
    n = input("Enter your binary number and hit 'ENTER'(exacly 16 digits)")
    n = int(n)
    n1 = n[15]
    n2 = n[14]
    n3 = n[13]
    n4 = n[12]
    n5 = n[11]
    n6 = n[10]
    n7 = n[9]
    n8 = n[8]
    n9 = n[7]
    n10 = n[6]
    n11 = n[5]
    n12 = n[4]
    n13 = n[3]
    n14 = n[2]
    n15 = n[1]
    n16 = n[0]

    if n1 > 1 or n2 > 1 or n3 > 1 or n4 > 1 or n5 > 1 or n6 > 1 or n7 > 1 or n8 > 1 or n9 > 1 or n10 > 1 or n11 > 1 or n12 > 1 or n13 > 1 or n14 > 1 or n15 > 1 or n16 > 1 :
        print("You don't have insert a binary number")
        convert()
    elif len(n) != 16:
        print("Your binary number is longer or shorter than 16 digits. Please enter EXACLY 16 digits!")
        convert()
    else:
        number = 1*n1 + 2*n2 + 4*n3 + 8*n4 + 16*n5 + 32*n6 + 64*n7 + 128*n8 + 256*n9 + 512*n10 + 1024*n11 + 2048*n12 + 4096*n13 + 8192*n14 + 16384*n15 + 32768*n16
        print (number)
        convert()
 
convert()
wenn ich dann meine Eingabe mache kommt immer dieser Fehlercode

Code: Alles auswählen

TypeError: 'int' object is not subscriptable
Danke schon mal im voraus
LG schweden1997
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Willkommen im Forum und zu Python!

Hier ist dein Problem:

Code: Alles auswählen

n = input("Enter your binary number and hit 'ENTER'(exacly 16 digits)")
n = int(n)
zusammen mit den Zeilen danach die `n` noch so verwenden wollen als waere es ein String und mit dem Index auf die Stellen zugreifen, eben "subskripten".
Wenn ich den Code danach so betrachte, dann solltest du `n = int(n)` loswerden.

Und fuer das Ungetuem danach - wenn du Namen durchnummerierst machst du etwas falsch:

Code: Alles auswählen

In [1]: def is_binary(numstring):
   ...:     return all(c in '01' for c in numstring)
   ...: 

In [2]: is_binary('0101001'), is_binary('23'), is_binary('42')
Out[2]: (True, False, False)
Fuer die Konvertierung von binaer nach dezimal solltest du `int(n, 2)` nutzen und die Rekursion wenn du Zahl nicht gueltig war solltest du auch durch eine Endlosschleife austauschen, mit einem entsprechend platzierten `break`. Denn sonst kann man nur 1000x falsch eingeben bis man an das Rekursionslimit kommt ;)
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Hui... der Code ist... *grausam*! Sorry, harte Worte, aber man kann da nichts schön reden.

Aber zu erst einmal zum Fehler: Du versuchst auf einem Integerobjekt einen Indexzugriff - das kann nicht klappen. Hier einmal simuliert:

Code: Alles auswählen

In [1]: i = 123

In [2]: i[0]
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-2-ff44243e4b36> in <module>()
----> 1 i[0]

TypeError: 'int' object is not subscriptable
(Wenn Du übrigens einen Fehler postest, dann bitte immer den *kompletten* Traceback; dann hätten wir nämlich auch sofort die Codestelle gesehen, wo der Fehler auftritt.)

Ich kapiere aber auch nicht, wieso Du den Eingabestring in einen Integerwert umwandeln willst? Du willst Du eigentlich eher eine Liste von Integerwerten:

Code: Alles auswählen

value = "1100101"
digits = map(int, value)
list(digits)
>>> [1, 1, 0, 0, 1, 0, 1]
Das Durchnummerieren von Namen ist (fast) immer ein Zeichen dafür, dass man eigentlich eine Datenstruktur verwenden sollte, oftmals eine Listenartige.

Wie schreibst Du Dein Programm um, wenn Du 32-Bit Zahlen wandeln willst? ;-)

Das Binden der einzelnen Stellen an eigene Namen erschwert auch das Prüfen, ob nur gültige Werte eingegeben wurden! Auch das kann man viel eleganter mit *einem* Objekt lösen:

Code: Alles auswählen

# Elemente in eine Liste packen
digits = list(map(int, value))
# alternativ so:
digits = [int(v) for v in value]

# Menge daraus ableiten
set(digits)
>>> set([0, 1])

# Und nun der "Trick": Vergleich mit der erwarteten Menge
set(digits) == {1, 0}
>>> True
Damit wäre auch das erledigt :-)

Selbst wenn Du als Anfänger `set` nicht kennst oder keine so elegante Idee gehabt hättest, so wärst Du zumindest zu diesem Konstrukt sicher in der Lage:

Code: Alles auswählen

value_is_valid = True
for value in digits:
    if value not in (0, 1):
        value_is_valid = False
        break
# hier kannst Du dann abfragen, ob `value_is_valid` `False` oder `True` ist
Die Berechnung der Zahl lässt sich auch einfacher in einer Schleife erledigen:

Code: Alles auswählen

value = 0
for index, digit in enumerate(reversed(digits)):
    value += 2 ** index * digit

value
>>> 101
`enumerate` erzeugt zu einem Iterable einfach einen Index. Damit hast Du die "Stelle" und den Wert (0 oder 1). Aus beidem kannst Du die entsprechende Potenz berechnen. Alles noch aufsummiert und fertig ist die Laube.

Auch das geht noch eleganter in einer List-Comprehension und der Funktion `sum`:

Code: Alles auswählen

sum(2**index for index, digit in enumerate(reversed(digits)) if digit == 1)
>>> 101
So, am Schluss dann noch der Demotivator: Python kann das schon von Hause aus:

Code: Alles auswählen

int("1100101", 2)
>>> 101
:-D
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
snafu
User
Beiträge: 6741
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Wenn man das über Mengen lösen möchte, dann geht es sogar noch etwas direkter:

Code: Alles auswählen

In [3]: {int(x) for x in '000110101001'} == {0, 1}
Out[3]: True
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

snafu hat geschrieben:Wenn man das über Mengen lösen möchte, dann geht es sogar noch etwas direkter:

Code: Alles auswählen

In [3]: {int(x) for x in '000110101001'} == {0, 1}
Out[3]: True

Code: Alles auswählen

>>> {int(x) for x in '111111111111'} == {0, 1}
False

Code: Alles auswählen

>>> set(map(int, '000110101001')).issubset({0, 1})
True
>>> set('000110101001').issubset(set('01'))
True
Oder am besten natürlich gleich die schon vorgeschlagene int-Lösung.
Das Leben ist wie ein Tennisball.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Oops, ja klar muss man `subset` nutzen :oops:

@snafu: Ich bin davon ausgegangen, dass man den String wandeln will. Will man das nicht, so würde ich es so angehen:

Code: Alles auswählen

set("1100101") <= {'0', '1'}
>>> True
Eine leere Eingabe hat man damit natürlich noch nicht geprüft.

@schweden1997: Falls es noch nicht klar geworden ist: `int` wirft einen `ValueError`, wenn im zu konvertierenden String ein ungültiges Digit vorkommt:

Code: Alles auswählen

int("1100401", 2)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-22-a8f501814871> in <module>()
----> 1 int("1100401", 2)

ValueError: invalid literal for int() with base 2: '1100401'
Wenn Du also auf diese Lösung setzt, brauchst Du nichts überpüfen - das macht `int` bereits für Dich.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
snafu
User
Beiträge: 6741
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Unter Beachtung von EyDu's berechtigtem Einwand wäre meine Lösung dann wahrscheinlich so:

Code: Alles auswählen

def is_binary(s):
    return {int(x) for x in s} <= {0, 1}
Oder eben mit Nutzung von `int()`:

Code: Alles auswählen

def is_binary(s):
    try:
        int(s, 2)
        return True
    except ValueError:
        return False
Bzw würde ich es wegen den Möglichkeiten von `int()` glaube ich gar nicht in eine Funktion auslagern, sondern als `try`-`except`-Block direkt in den Code packen.
Antworten