Seite 1 von 1
Liste wirft falsche Zahlen raus
Verfasst: Montag 29. Oktober 2018, 09:32
von Beginner123
Hallo, ich habe im Folgenden Code versucht über eine Liste zu iterrieren und dabei alle Elemente der Liste, die keine Zahlen (float oder int) sind aus der ursprünglichen Liste zu entfernen.
Leider schmeißt er mir die floats immer mit raus, woran kann das liegen?
Hier einmal mein Versuch:
Code: Alles auswählen
items = ["e", 1.23,"k",1.4,-1,"l"]
def test(items):
items2 = items.copy()
for i in items2:
if (type(i) == (int or float)):
pass
else:
items.remove(i)
return items
test(items)
Re: Liste wirft falsche Zahlen raus
Verfasst: Montag 29. Oktober 2018, 09:47
von Bolitho
Warum machst du die Schleife nicht direkt auf der Liste?
Code: Alles auswählen
items = ["e", 1.23,"k",1.4,-1,"l"]
def test(items):
for i in items:
if (type(i) == (int or float)):
pass
else:
items.remove(i)
return items
test(items)
Re: Liste wirft falsche Zahlen raus
Verfasst: Montag 29. Oktober 2018, 09:56
von __deets__
Die Bedingung ist aber immer noch falsch.
x == a or b
ist nicht was du denkst. Das musst du dir so geklammert vorstellen:
(x == a) or b
Und dann ist klar, dass das IMMER wahr ist, weil float wahr ist.
Stattdessen
x == a or x == b
benutzen, oder gleich
isinstance(x, (a, b))
Re: Liste wirft falsche Zahlen raus
Verfasst: Montag 29. Oktober 2018, 10:05
von Sirius3
@__deets__: falsche Klammerung, die Klammer ist um (int or float) was immer int ist, weil int schon wahr ist.
@Beginner123: Deine Bedingung lautet daher nur `type(x) == int`. In Wirklichkeit willst Du aber wahrscheinlich nicht nur int und float rauswerfen, sondern alle Arten von Zahlen? Das macht man in Python aber nicht, indem man eine Liste verändert, sondern indem man eine neue Liste generiert, die nur die Elemente enthält, die man behalten will.
Code: Alles auswählen
from numbers import Number
def test(items):
return [x for x in items if not isinstance(x, Number)]
items = ["e", 1.23,"k",1.4,-1,"l"]
print(test(items))
oder mit filter_false
Code: Alles auswählen
from itertools import filterfalse
def test(items):
return list(filterfalse(lambda x: isinstance(x, Number), items))
Sonstige Anmerkungen:
Bei einem if-Block mit nur `pass` würde man die Bedingung umdrehen und den else-Block als if-Block nehmen.
Eine Funktion sollte möglichst nicht die Liste ändern, die man ihr übergibt, und wenn, dann das deutlich in der Dokumentation zur Funktion beschreiben und dann None zurückgeben.
@Bolitho: die Schleife direkt über die Liste zu machen führt zu falschen Ergebnissen, wenn man innerhalb der Schleife die Liste ändert.
Re: Liste wirft falsche Zahlen raus
Verfasst: Montag 29. Oktober 2018, 10:13
von __deets__
Sirius3 hat geschrieben: Montag 29. Oktober 2018, 10:05
@__deets__: falsche Klammerung, die Klammer ist um (int or float) was immer int ist, weil int schon wahr ist.
Bist du sicher? AFAIK hat == höhere Präzedenz. Also muss darum geklammert werden.
Edit: “muss geklammert werden” soll natürlich meinen, dass man sich die so denken muss.
Re: Liste wirft falsche Zahlen raus
Verfasst: Montag 29. Oktober 2018, 11:16
von Beginner123
Okay danke für die Hilfe, ich muss mich im Moment an den Unistoff halten und darf deshalb noch nichts importieren, ich sollte einmal die urprüngliche Liste ändern und einmal die gleiche Aufgabe bloß ohne die ursprüngliche Liste zu verändern.
@_deets_ Mit type(i) == int or type(i) == float funktioniert es jetzt
@Sirius für die Praxis sehen deine Beispiele deutlich besser aus, deshalb werde ich mir die Vorgehensweise auf jeden Fall merken!
Re: Liste wirft falsche Zahlen raus
Verfasst: Montag 29. Oktober 2018, 11:28
von Sirius3
@__deets__: die Klammern sind aber da, AFAIK haben die höchste Priorität: type(i) == (int or float)
@Beginner123: type zu benutzen ist aber trotzdem im Allgemeinen falsch, richiger ist __deets__ letzte Variante: `isinstance(x, (a, b))`
Re: Liste wirft falsche Zahlen raus
Verfasst: Montag 29. Oktober 2018, 11:46
von __deets__
@Sirius: ah. ich habe die von ihm selbst gesetzten beim schreiben der Antwort schon wieder vergessen. Und im Kopf nur das falsche Muster "x == a or b" gehabt, das ja so auch oft vorkommt. Klar, seine Klammerung macht das natuerlich noch problematischer.
Re: Liste wirft falsche Zahlen raus
Verfasst: Montag 29. Oktober 2018, 11:56
von Beginner123
@Sirius Okay merke ich mir, wir haben in der Uni nur type als Option bekommen und den Typ herauszufinden, warum genau darf ich das nicht dafür nutzen? An welcher Stelle wäre type angebracht?
Re: Liste wirft falsche Zahlen raus
Verfasst: Montag 29. Oktober 2018, 12:01
von __deets__
Das Problem mit type ist, dass es fragil bei Vererbung ist. Wenn du sowas hier machst, siehst du das Problem:
Code: Alles auswählen
class A:
pass
class B(A):
pass
b = B()
print(type(b) == A)
print(isinstance(b, A))
Darum ist es besser, isinstance zu benutzen. Und es hat auch gleich einen angenehmen Mechanismus, mehrere Typen abzupruefen, was du ja tun musst.
Re: Liste wirft falsche Zahlen raus
Verfasst: Montag 29. Oktober 2018, 12:11
von Beginner123
Okay gut zu wissen, danke euch
Re: Liste wirft falsche Zahlen raus
Verfasst: Montag 29. Oktober 2018, 12:12
von snafu
@Beginner123: Am flexibelsten ist tatsächlich Number aus dem numbers-Modul. Damit fängt man alle Arten von Zahlen ab. Auch sowas wie Decimal. Wenn ihr das noch nicht hattet, dann nimm erstmal type(). Ein guter Dozent weist euch noch auf isinstance() hin. Dies ist nämlich das bevorzugte Vorgehen für Typprüfungen in Python.
Re: Liste wirft falsche Zahlen raus
Verfasst: Dienstag 30. Oktober 2018, 11:39
von __blackjack__
Wobei man vielleicht noch erwähnen sollte das die wirklich bevorzugte Methode für Typprüfungen in Python, wie in den meisten anderen objektorientierten Programmiersprachen, ist es gar nicht zu tun. Explizite Typprüfungen sind ein „code smell“. Es gibt einige wenige Fälle in denen man sie braucht, aber allgemein sollte man da immer zweimal drüber nachdenken warum man sie braucht oder ob man sie tatsächlich braucht. Bei gegebenen Beispiel könnte man sie beispielsweise die Frage stellen warum da überhaupt Zahlen und Zeichenketten in einer Liste gemischt werden.
Bei Python kommt noch hinzu, dass man mit expliziten Typprüfungen das „duck typing“ aushebelt und potentiell gültige Werte falsch behandelt weil der Typ ”nicht stimmt”. `Number` funktioniert zum Beispiel auch nur wenn die zahlähnlichen Typen die man vorliegen hat, auch tatsächlich davon abgeleitet sind, oder zumindest nachträglich registriert worden sind. Da kann man bei den Typen aus der Standardbibliothek wohl von ausgehen, aber ausserhalb kann das dann schon wieder anders aussehen.
Trotzdem könnte man hier auch noch `functools.singledispatch` aus der Standardbibliothek erwähnen wenn man schon beim Thema Typprüfungen ist. Und beispielsweise `decorator.dispatch_on` wenn man auch externe Module hinzuzieht.