Variable auf Datencollection prüfen

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
NoUseForAName
User
Beiträge: 10
Registriert: Montag 22. März 2021, 17:21

Ich habe erst seit kurzem mit Python zu tun, einige Begriffe sind mir daher nicht geläufig, wie etwa hier. Ich habe etwas gegooglet, aber keine Klassenhierarchien gefunden wie ich sie etwa von Java kenne. Benötigen tu ich eine eigentlich völlig simple Abfrage, bei der beim Iterieren über etwas geprüft wird ob der Value ein Integer oder String ist, oder aber eine Liste oder eine andere Sammlung über die man dann wieder iterieren müsste um alles auszugeben. Dabei wäre es aber erstmal egal um welche Art Datensammlung es sich handelt. Es können zB 3mal geschachtelte Listen sein, die dann wieder ausgegeben würden, oder aber auch nur ein einzelner String, die Struktur ist vorher nicht bekannt.


Also sowas wie

Code: Alles auswählen

if element is collection:
	#	über element iterieren
			if content is collection:
		#		über content iterieren
					etc...
			else:
				print(content)
	  else:
	  	 print(element)				
Frage - Kann ich überprüfen ob eine Variable eine Sammlung von Daten enthält, ohne die einzelnen Typen (Liste,Tuple,Dictionary...) explizit durchzugehen ? Und gibt es eine Funktion die einem erlaubt über jede Sammlung zu iterieren, unabhängig ob key -> value Paare vorhanden sind oder nicht ?
Benutzeravatar
__blackjack__
User
Beiträge: 14076
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@NoUseForAName: So allgemein geht das gar nicht. Man kann nicht sicher prüfen ob etwas iterierbar ist, ohne tatsächlich darüber zu iterieren. Auf der anderen Seite sind Zeichenketten iterierbar — und liefern wieder Zeichenketten (mit einem Zeichen), die aber wieder iterierbar sind. Das heisst mindestens mal Zeichenketten, möchte man da ausnehmen, auch wenn die eine ”Collection” von Zeichen sind.

Collection gibt es so als Begriff in Python nicht. Es gibt Sequenzen; da fallen beispielsweise Listen, Tupel, und Zeichenketten drunter. Und es gibt Abbildungen; da fallen beispielsweise Wörterbücher drunter. Und allgemein eben iterierbare Objekte. Beispielsweise alle bisher genannten, und zum Beispiel Mengen oder Dateiobjekte. Wobei iterierbar nicht bedeutet, dass man da den gesamten Inhalt bekommen muss. Bei Wörterbüchern bekommt man die Schlüssel, aber nicht die Werte. Dafür müsste man entweder `values()` für die Werte aufrufen, oder `items()` für Tupel aus Schlüsseln und Werten.

Was willst Du denn *eigentlich* für ein Problem lösen? Nicht das Du am Ende so etwas wie das `pprint`-Modul aus der Standardbibliothek selbst bastelst. Oder alternativ das externe `prettyprinter`-Modul. Oder wenn Du da eigentlich eine Datenstruktur hast die aus JSON-”kompatiblen” Werten besteht, `json.dumps()`.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Benutzeravatar
noisefloor
User
Beiträge: 4195
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

die formelle, aber IMHO verständliche Erklärung für "iterierbar" ist in der Python Doku zu finden: https://docs.python.org/3/glossary.html#term-iterable

Ein potentielles weiteres Problem deines Ansatzes: wenn du eine Endlosgenerator bekommen würdest, hinge dein Prog in einer Endlosschleife, weil Endlosgeneratoren endlos iterierbar sind. Ob ein Generator endlos ist kann man vorab nicht prüfen.

Gruß, noisefloor
Benutzeravatar
DeaD_EyE
User
Beiträge: 1244
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Man kann nicht sicher prüfen ob etwas iterierbar ist, ohne tatsächlich darüber zu iterieren.
Python-Objekte oder irgendwas Theoretisches?

Falls es um Python geht, kann man: collections.abc.Iterable und collections.abc.Iterator.
Iteratoren haben die Methode __next__ und Iterierbare Objekte haben die Methode __iter__.
Das ist mit das einfachste und wichtigste Protokoll in Python.
Die Größe ist unbekannt, aber das Verhalten nicht.

Schon mal überprüft, ob eine Funktion einen Generator zurückliefert, ohne die Funktion aufzurufen?
Geht auch: inspect.isgeneratorfunction
Prüfen, ob etwas ein generator ist: inspect.isgenerator
__blackjack__ hat geschrieben: Mittwoch 17. November 2021, 18:51 Collection gibt es so als Begriff in Python nicht.
https://docs.python.org/3/library/colle ... Collection
ABC for sized iterable container classes.
New in version 3.6.
Eine abstrakte Klasse, die aussagt, dass das Objekt iterierbar sein muss, eine Größe haben muss und den in Operator unterstützt.
Also müssen die Methoden __len__, __iter__ und __contains__ implementiert werden.
Fehlen diese Methoden, lässt sich die Klasse nicht instanziieren (TypeError).

Man könnte auch auf typing.Collection verweisen. Auch damit funktioniert isinstance.

---
Kann ich überprüfen ob eine Variable eine Sammlung von Daten enthält, ohne die einzelnen Typen (Liste,Tuple,Dictionary...) explizit durchzugehen ?
Wenn du die Daten z.B. von einem Webserver über eine offizielle API bekommst, ist vorher bekannt wie die Datenstruktur ist (Doku des Anbieters). Diese kann man dann überprüfen, aber die Struktur ändert sich nicht (meistens). Dann fragt man genau die Daten ab, die man braucht und falls sich in der Antwort z.B. eine Liste befindet, kann man darüber iterieren.


Wenn rein hypothetisch irgendwelche Python-Datenstrukturen iteriert werden sollen, kann man auf collections.abc und/oder typing zurückgreifen, um Arten von Typen zu erkennen. Interessant wären: Sequence und Mapping.

Vorsicht vor bytes und str. Das sind auch Sequenzen.

Code: Alles auswählen

from collections.abc import Sequence

print(isinstance("Test", Sequence))
Liefert ein True zurück. Doof, weil man darüber nicht iterieren möchte.
Also muss man diesen speziellen Fall auch abfangen.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Benutzeravatar
__blackjack__
User
Beiträge: 14076
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@DeaD_EyE: Python-Objekte ganz praktisch. Und `Collection` kenne ich nicht weil Typannotationen doof sind. Das ist kein Python, das haben da irgendwelche Trolle reingeschmuggelt. 😈 Und das funktioniert auch nur wenn man diese `abc`\s benutzt. Also nicht nur bei der Abfrage sondern die Klassen von deren Objekten man das abfragen will müssen das auch verwenden, oder man muss es nachträglich registrieren. Für letzteres müsste man aber wieder vorher wissen was man da an Typen bekommt/erwartet.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Antworten