Bitte ein komplettes Beispiel für die TypeError-Exeption

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.
Benutzeravatar
Strawk
User
Beiträge: 227
Registriert: Mittwoch 15. Februar 2017, 11:42
Wohnort: Aachen
Kontaktdaten:

Hallo!

Eine Funktion nested_sum soll die Elemente vom Typ integer, die in einer verschachtelten Liste sind (nested list) zusammen-/aufaddieren.

Ich möchte eine Exeption vom Typ TypeError werfen (und fangen?), wenn das zu untersuchende Einzelelement kein Integer ist und wenn die Einzelelemente nicht in einer verschachtelten Liste (nested list) sind. Bitte ein komplettes Beispiel, aus dem hervorgeht, WIE DER EXEPTION ÜBERHAUPT DER ERWARTETE TYP MITGETEILT WIRD.

Ich habe das gegoogelt, finde aber nur try- und catch-Blöcke, ohne dass ich wüsste, wie man der Exeption denn nun sagt: Hier muss eine Liste sein, sonst wirf, hier muss ein integer sein, sonst wirf.

Strawk :)
Ich programmiere erfolglos, also bin ich nicht.
BlackJack

@Strawk: Das sagt man der Exception gar nicht. Eine Ausnahme prüft nichts, das musst Du selbst tun. Oder Du machst etwas ohne zu prüfen und das löst eine Ausnahme aus die Du behandeln kannst. Komplettes Beispiel um eine `TypeError`-Ausnahme auszulösen:

Code: Alles auswählen

raise TypeError('was immer als text sinn macht')
Komplettes Beispiel um eine `TypeError`-Ausnahme zu behandeln:

Code: Alles auswählen

try:
    # irgendwas das einen TypeError auslösen kann
except TypeError as error:
    # Hier *sinnvoll* (das ist *ganz* wichtig!) auf die Ausnahme reagieren
Der letzte Kommentar ist wirklich wichtig! Wenn man da nichts sinnvolles macht, dann sollte man es ganz bleiben lassen, denn das ist dann in dem Fall die sinnvollere Alternative.

Statt mit einer Suchmaschine solche Grundlagen zu suchen, macht es vielleicht mehr Sinn ein zusammenhängendes Tutorial für die Grundlagen zu verwenden. In der Python-Dokumentation befindet sich eins. Das hat auch ein Kapitel zu Ausnahmen und Ausnahmebehandlung.

Falls das eine Hausaufgabe ist, wird eventuell tatsächlich verlangt, das Du auf ganze Zahlen und Listen testest. Das verhindert allerdings, dass man auch andere addierbare Typen und Sequenzen verwendet. Eine generischere Lösung würde einfach versuchen die Objekte als iterier- und addierbar zu behandeln und entsprechend auf Ausnahmen reagieren. Also zum Beispiel die Iteration versuchen, und wenn das nicht geht, das Objekt als addierbar behandeln. Solltest Du auf Typen testen müssen, brauchst Du noch `isinstance()`. Oder `functools.singledispatch()` oder den Backport davon für Python 2. :-)
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Der Exception wird nichts mitgeteilt. Die wird geworfen. WARUM sie geworfen wird liegt in deiner Hand. ZB weil du mit "isinstace(item, list)" geprueft hast, ob etwas eine Liste ist. Oder mit "isinstance(item, (int, long))" eine Ganzzahl.
Benutzeravatar
Strawk
User
Beiträge: 227
Registriert: Mittwoch 15. Februar 2017, 11:42
Wohnort: Aachen
Kontaktdaten:

Ich kann dem die zu verwendende Syntax nicht entnehmen. Ist da irgendwo ein "if" drin, muss das irgendwo ein "if" rein? Bitte ausführlicher, genauer. Danke! Wenn ich der Variable "l" einen Einzelwert zuweise, dann muss die Exeption ausgelöst werden, denn laut Aufgabe, MUSS es eine Liste sein. Dennoch löst l = 'willi' keine/n TypError aus, denn das ist eine legale Zuweisung. WO WIRD DER EXEPTION BEIGEBRACHT/MITGETEILT, was zulässig ist und was nicht?
Ich programmiere erfolglos, also bin ich nicht.
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ja, es muss ein if darein. Denn wie du schon festgestellt hast ist das binden eines Namens keine Operation, bei der eine typprüfung stattfindet. Das musst du selbst machen.
Benutzeravatar
Strawk
User
Beiträge: 227
Registriert: Mittwoch 15. Februar 2017, 11:42
Wohnort: Aachen
Kontaktdaten:

Bitte den betreffenden Codeschnipsel hier komplett wiedergeben, inklusive

try
except
raise
catch

Wo kommt was hin und wo steht der If-Zweig? (Hier Beispiel nur Liste oder keine Liste)

Danke! :K
Ich programmiere erfolglos, also bin ich nicht.
BlackJack

@Strawk: Ich denke das ist *Deine* Aufgabe. Auch ``if`` ist Thema im Tutorial in der Python-Dokumentation.
Benutzeravatar
Strawk
User
Beiträge: 227
Registriert: Mittwoch 15. Februar 2017, 11:42
Wohnort: Aachen
Kontaktdaten:

Ich versuche mich seit 2009 in VBA und seit 2011 in PHP (zugegeben mit mäßigem Erfolg) und weiß, wie "if" funktioniert. Was ich nicht weiß und gern von euch wüsste: Wie und wo (rein von der Syntax/Befehlsabfolge her) wird definiert, DASS die Exception DANN geworfen werden soll.

Denn: Wenn y = 0 ist, wird x/y scheitern. l = 'willi' scheitert aber nicht; ich muss das Scheitern selber implementieren.

*verzweifel*
Ich programmiere erfolglos, also bin ich nicht.
BlackJack

@Strawk: Du weisst alles was man braucht. Wie ``if`` funktioniert, wie man eine Ausnahme auslöst, und welche Funktion man zum Testen auf Typen benutzt. Bis auf das ``if`` haben wir alles gezeigt was man braucht.

Edit: So sähe es übrigens mit `singledispatch()` aus:

Code: Alles auswählen

from __future__ import absolute_import, division, print_function
try:
    from functools import singledispatch
except ImportError:
    from singledispatch import singledispatch


@singledispatch
def nested_sum(item):
    raise TypeError('unexpected value of type {0.__name__}'.format(type(item)))



def identity(item):
    return item


nested_sum.register(int, identity)


try:
    nested_sum.register(long, identity)
except NameError:
    pass  # Python >2 has no `long` type anymore.


@nested_sum.register(list)
def _(items):
    return sum(nested_sum(item) for item in items)


def main():
    print(nested_sum(42))
    print(nested_sum([1, 2, [4711, 23], 42]))
    print(nested_sum(1000000000000000000000000000000000000))
    print(nested_sum(None))


if __name__ == '__main__':
    main()
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

Strawk hat geschrieben:Denn: Wenn y = 0 ist, wird x/y scheitern. l = 'willi' scheitert aber nicht; ich muss das Scheitern selber implementieren.
Genau. Wenn y = 0 ist, dann hast Du Glück. Die Ausnahme wirft sich von alleine. Manuell wird eine mit 'raise' geworfen. Nun mußt Du nur noch testen, wann das erforderlich sein soll, z.B. bei I = 'willi'. Eine klassische, häufig vorkommende Situation.
Benutzeravatar
Strawk
User
Beiträge: 227
Registriert: Mittwoch 15. Februar 2017, 11:42
Wohnort: Aachen
Kontaktdaten:

Code: Alles auswählen

def nested_sum(l):
    try:
        if not isinstance(l, list):
                    raise TypeError
    except TypeError:
            print 'no list'
    
    i = 0
    for e in l:
        try:
            if not isinstance(e, list):
                    raise TypeError
        except TypeError:
            print 'no list'
        
        i1 = 0
        for e1 in e:
            try:
                if not isinstance(e1, int):
                    raise TypeError
            except TypeError:
                print 'no integer'
            i1 += e1
        i += i1
    return i

l = [['willi',2,2],[3,3,3],[4,4,4]]
print nested_sum(l)
Leider bekomme ich nicht 'meine' (die von mir selber definierten) Fehlermeldungen. Was ist falsch?
Zuletzt geändert von Anonymous am Montag 15. Mai 2017, 22:26, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Ich programmiere erfolglos, also bin ich nicht.
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ausnahmen auszulösen um sie dann sofort abzufangen ist sinnlos. Dann kannst du doch gleich ein print in den if Block packen.

Und auch wenn das jetzt kein schöner Code ist - eigentlich sollte es klappen. Was passiert denn?
Benutzeravatar
Strawk
User
Beiträge: 227
Registriert: Mittwoch 15. Februar 2017, 11:42
Wohnort: Aachen
Kontaktdaten:

Hallo! :)

Code: Alles auswählen

def nested_sum(l):
    try:
        if not isinstance(l, list):
                    raise TypeError
    except TypeError:
            return 'no list'
    
    i = 0
    for e in l:
        try:
            if not isinstance(e, list):
                    raise TypeError
        except TypeError:
            return 'no list'
        
        i1 = 0
        for e1 in e:
            try:
                if not isinstance(e1, int):
                    raise TypeError
            except TypeError:
                return 'no integer'
            i1 += e1
        i += i1
    return i

l = [[2,2,2],[3,3,3],7]
print nested_sum(l)
l = [['willi',2,2],[3,3,3],[4,4,4]]
print nested_sum(l)
l = [[2,2,2],[3,3,3],[4,4,4]]
print nested_sum(l)
l = 'willi'
print nested_sum(l)
Ich bekam nicht meine eigenen Fehlermeldungen, sondern Sachen wie: "int is not iterable".
Hier eine hoffentlich bessere Version. Hat das Sinn, was ich gestrickt habe? :? :roll:

Grüße
Strawk
Ich programmiere erfolglos, also bin ich nicht.
BlackJack

@Strawk: Na das Problem ist wie schon gesagt das Du die Ausnahmen die Du auslöst auch gleich wieder ”behandelst” und zwar in dem Du eine Ausgabe mit `print()` machst, und dann der Code aber weitergeht als wenn die Ausnahme gar nicht da gewesen wäre.

Du willst doch eigentlich prüfen ob es sich um eine Liste handelt, und dann damit etwas bestimmtes machen, oder ob es sich um eine ganze Zahl handelt, und damit dann etwas bestimmtes machen, oder ob es weder Liste noch Zahl war, und *nur dann* einen `TypeError` auslösen. Den Liste und Zahl sind ja keine Fehler.

Ausserdem gehe ich mal ganz stark davon aus, das „nested list“ jede beliebige mögliche Verschachtelung meint, also beispielsweise auch ``[1, 2, [3, [4, 5]], 6, [[7]]]``. Und nicht nur etwas ”Zweidimensionales” wo nur auf der zweiten Ebene die Zahlen und nur Zahlen stehen.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Strawk hat geschrieben:Ich möchte eine Exeption vom Typ TypeError werfen (und fangen?)
Das Werfen ist einfach. Du machst einfach etwas, das nicht mit etwas Anderem als mit einer Integer geht, etwa:

Code: Alles auswählen

a = 3.5 # das ist keine Integer
a & 1 # und das geht dann nicht und wirft eine Exception
Und beim Fangen kommt es dann darauf an, was Du damit tun willst.

- Fangen, eine Fehlermeldung ausgeben und weitermachen
- Fangen, dazu noch eine Fehlermeldung ausgeben und abbrechen

Fall 1: Fangen, eine Fehlermeldung ausgeben und weitermachen

Code: Alles auswählen

a = 3.5
try:
    a & 1
except TypeError:
    print("Warum war das keine Integer, aber egal, ich mache weiter")
Fall 2: Fangen, dazu noch eine Fehlermeldung ausgeben und abbrechen

Code: Alles auswählen

a = 3.5
try:
    a & 1
except TypeError:
   print("Wieder keine Integer, ich gebe es jetzt endlich auf")
   raise
Verständlich?
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

Des Nachts der Code-Troll sich befleißt
Ein jedes Thema an sich reißt
Die Funktionen leuchten weit und hell
Allein es stört der Coding-Smell.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@Strawk: ich habe noch etwas vergessen. True und False zählen auch als Integer. Das solltre man auch noch abfangen:

Code: Alles auswählen

a = True
if istype(a,bool):
    a = 3.5
a & 1
Und genauso geht dann natürlich auch:

Code: Alles auswählen

if not isinstance(l, list):
    3.5 & 1
Benutzeravatar
noisefloor
User
Beiträge: 3843
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

@Alfons Mittelmeyer
True und False zählen auch als Integer
Du musst ein anderes Python benutzen als alle anderen hier im Forum. Du musst. Kann gar nicht anders. Und streite da am besten erst gar nicht ab, dass macht's nur schlimmer.

Gruß, noisefloor
BlackJack

@noisefloor: Nee, das stimmt schon:

Code: Alles auswählen

In [1]: isinstance(True, int)
Out[1]: True

In [2]: isinstance(False, int)
Out[2]: True

In [3]: issubclass(bool, int)
Out[3]: True

In [4]: True + True
Out[4]: 2

In [5]: 42 / False
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
<ipython-input-5-5e0a6f844f47> in <module>()
----> 1 42 / False

ZeroDivisionError: integer division or modulo by zero

In [6]: -True
Out[6]: -1
Da Vererbung eine „ist-ein(e)“-Beziehung ist, braucht man das aber nicht extra testen, denn `bool`-Werte *sind* `int`-Werte, also ist es okay das auch `True` und `False` addiert werden können, denn es sind ja (auch) ganze Zahlen.
Benutzeravatar
noisefloor
User
Beiträge: 3843
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

aha, ok. Wieder was gelernt. Mein Gedankengang war, dass bool ein eigener Datentyp ist. Bis zum subclassing hatte ich nicht gedacht.

@Alfons Mittelmeyer: wir nutzen doch das gleiche Python, sorry.

Gruß, noisefloor
Antworten