Seite 1 von 1

Listen durchsuchen und Elemente testen

Verfasst: Dienstag 1. Dezember 2020, 17:05
von jekyllvshyde
Hey ich habe ein kleines Problem mit meiner Aufgabe. Ich soll mittels Rekursion testen ob alle Elemente einer Liste integer sind. Ich habe folgende Funktion geschrieben und habe nur das Problem dass die Funktion zwar abbricht aber mir den falschen boolschen Wert ausgibt wenn ich mich in einer Liste in der Liste befinde. Kann mir jemand erklären wo mein Fehler ist. Für mich als Anfänger müsste das Programm nach dem Rekursiven Aufruf von intSuperliste, beim durchlaufen der for Schleife erkennen, dass 4.3 kein integer oder Liste ist und sagen intBool = False und danach die for Schleife abbrechen.

Code: Alles auswählen

N = [1,3,[4.3,5]]

def intSuperliste(L):
    intBool = True
    for item in range(len(L)):
        if type(L[item]) != int and type(L[item]) != list:
            intBool = False
            break
        elif type(L[item]) == list:
            intSuperliste(L[item])
    return intBool
    
print(intSuperliste(N))

Re: Listen durchsuchen und Elemente testen

Verfasst: Dienstag 1. Dezember 2020, 19:18
von Bolitho
so ganz verstehe ich die Aufgabenstellung und das Problem nicht.

Ein rekursiver Aufruf würde ja z.B. das erste Element der Liste testen und wenn es ein Integer ist, das nächste Element der Liste testen. So lange bis die Liste leer ist und dann True durch die ganze Kette zurückgeben.
Das dritte Listenelement ist eine Liste und das ist ja nunmal selbst kein Integer. Also müsste hier False zurückgegeben werden.

Dein Programm geht in die Richtung, dass eine Liste auf Ganzzahlen geprüft wird und wenn eine Liste enthalten ist, diese rekursiv geprüft wird. Das wäre aber eine andere Aufgabenstellung als beschrieben.

Zudem schau dir bitte mal den StyleGuide von Python an:
https://www.python.org/dev/peps/pep-000 ... onventions
z.B. werden Funktionen und Variablen mit Kleinbuchstaben benannt, mehrere Wörter mit _ getrennt. L als Eingabewert ist auch nicht selbstredend und kein guter Name.

Re: Listen durchsuchen und Elemente testen

Verfasst: Mittwoch 2. Dezember 2020, 09:46
von Sirius3
@jekyllvshyde: Dein Problem ist, dass der Rückgabewert der Rekursiven Aufrufe nicht verwendet wird.

Der Funktionsname ist superschlecht, der Funktionsname sollte eine Tätigkeit beschreiben, was die Funktion macht, nämlich prüfen, ob in einer verschachtelten Liste nur Zahlen enthalten sind, also are_only_ints_in_list_of_lists.
Variablennamen schreibt man wie Funktionen in Python komplett klein, einbuchstabige Namen sind im allgemeinen schlecht, weil nichtssagen.
Direkte Typ-Prüfung macht man nicht, wenn es wirklich nötig ist, würde man isinstance benutzen.
Die Reihenfolge der if-Abfragen ist schlecht, weil im ersten if etwas geprüft wird, was im zweiten if nochmal gemacht wird.
Über einen Index iteriert man in Python nicht, sondern über die Elemente der Liste direkt. `item` ist auch der verwirrendste Name, den es gibt, für einen Index.
Datentypen haben in einer Variable nichts verloren, das Bool gehört also weg, und das int ist dann nicht wirklich das, was die Variable enthält.
Was soll eigentlich passieren, wenn L keine Liste ist?

Das ganze mal ohne rekursiven Aufruf:

Code: Alles auswählen

def are_only_ints_in_list_of_lists(lists):
    to_be_checked = [lists]
    while to_be_checked:
        for item in to_be_checked.pop():
            if isinstance(item, list):
                to_be_checked.append(item)
            elif not isinstance(item, int):
                return False
    return True
    
test_data = [1,3,[4.3,5]]
print(are_only_ints_in_list_of_lists(test_data))
Die explizite Typprüfung macht aber das Duck-Typing kaputt, so dass man andere iterierbare Container nicht verwenden kann, und die Frage ist, ob wirklich nur int oder alle Ganzzahlen erlaubt sein sollen.

Code: Alles auswählen

from numbers import Integral
def are_only_ints_in_list_of_lists(lists):
    to_be_checked = [lists]
    while to_be_checked:
        iterable = to_be_checked.pop()
        for item in iterable:
            if item is iterable:
                return False
            elif not isinstance(item, Integral):
                try:
                    iter(item)
                except TypeError:
                    # no iterable
                    return False
                else:
                    to_be_checked.append(item)
    return True