[gelöst] Großes Problem mit isinstance.

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
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Hallo, ich hab da ein großes Problem mit isinstance.

Vorweg: Bitte nicht über den Sinn einer Typprüfung diskutieren! Ich bin mir sehr wohl über den Sinn oder Unsinn bewusst! Ich kann euch aber nun schlecht erklären wozu ich das brauche, ohne euch den Code zu posten und zu erklären was ich vor habe. Daher frage ich lieber direkt wie man folgendes Problem lösen kann. Falls einige wissen wollen wofür ich das brauche, poste ich gerne meinen bisherigen Code mit einer Erklärung dazu (habe ich ehe irgendwann vor wenn mein Modul fertig ist).


Back2Topic:

Ich brauche an einer stelle ein Type Überprüfung, wonach entschieden wird welch Funktion aufgerufen wird.

Eigentlich macht man das folgendermaßen:

Code: Alles auswählen

if isinstance(options[option], bool):
    return self._is_bool(section, option)
[...]
Aber wenn ich nun einen int werte habe besteht diese Prüfung auch, da ja bool von int abgeleitet ist! Ich könnte heulen. :evil: Das soll aber nicht sein, weil ich genau wissen will ob es genau vom Type bool ist und int wo ander abgefragt werden soll :-[

Hmm, andere Ansatz den aber BlackJack ja nicht für gut hält (berechtigterweise!):

Code: Alles auswählen

if str(type(options[option])) == "<type 'bool'>":
    return self._is_bool(section, option)
elif str(type(options[option])) == "<type 'int'>":
    return self._is_digit(section, option)
[...]
Die Methode funktioniert, ist aber nicht sauber, da beim int abschnitt alles vom Type long ignoriert wird und anderes auch (Dafür noch ne if abfrage zu opfern halte ich für nicht sinnvoll)

Was für eine Möglichkeit gibt es noch um direkt nur auf den Type hin zu überprüfen? Oder kann man isinstance beibringen das er bool nicht zum Type int und long Zählt? xD

lg
Zuletzt geändert von sape am Mittwoch 15. November 2006, 13:45, insgesamt 1-mal geändert.
BlackJack

XtraNine hat geschrieben:Hmm, andere Ansatz den aber BlackJack ja nicht für gut hält (berechtigterweise!):

Code: Alles auswählen

if str(type(options[option])) == "<type 'bool'>":
    return self._is_bool(section, option)
elif str(type(options[option])) == "<type 'int'>":
    return self._is_digit(section, option)
[...]
Die Methode funktioniert, ist aber nicht sauber, da beim int abschnitt alles vom Type long ignoriert wird und anderes auch (Dafür noch ne if abfrage zu opfern halte ich für nicht sinnvoll)
Die Methode "funktioniert" ist relativ. Das da "<type 'bool'>" rauskommt ist "Zufall", es ist nirgends garantiert das die Zeichenkette so aussieht.
Was für eine Möglichkeit gibt es noch um direkt nur auf den Type hin zu überprüfen? Oder kann man isinstance beibringen das er bool nicht zum Type int und long Zählt? xD
Du willst also das Python Dich belügt? ;-)

Schau Dir mal `issubclass()` an.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

XtraNine hat geschrieben:Was für eine Möglichkeit gibt es noch um direkt nur auf den Type hin zu überprüfen? Oder kann man isinstance beibringen das er bool nicht zum Type int und long Zählt?
Hi XtraNine!

Bei meinen Tests wird 1 nicht als ``BooleanType`` ausgegeben. Es könnte aber auch sein, dass das in früheren Python-Versionen der Fall ist.

Du könntest ja zuerst prüfen ob es sich um einen Integer- oder Long-Typ handelt und erst *danach*, ob es sich um einen Boolean-Typ handelt.

Wenn du auf einen EXAKTEN Typ prüfen willst, dann wäre ``isinstance`` nicht unbedingt meine erste Wahl. Dafür würde ich eher ``type`` verwenden.

Code: Alles auswählen

>>> isinstance(1, bool)
False
>>> import types
>>> isinstance(1, (types.IntType, types.LongType))
True
>>> type(1) == types.IntType
True
>>> type(1) == types.LongType
False
>>> isinstance(True, types.BooleanType)
True
>>> isinstance(1, types.BooleanType)
False
>>> type(1) in (types.IntType, types.LongType)
True
>>> type(False) in (types.IntType, types.LongType)
False
>>> 
Oder habe ich da etwas falsch verstanden?

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
BlackJack

Das `types` Modul ist in aktuellen Python-Versionen auch nicht mehr nötig, man kann direkt mit den Konstruktoren vergleichen:

Code: Alles auswählen

In [8]: type(True) == bool
Out[8]: True

In [9]: type(1) == bool
Out[9]: False
Allerdings gab's mal in alten Versionen soweit ich weiss `True` und `False` einfach als Namen für 1 und 0 und nicht als eigenständigen Typ. Da kann man eine saubere Trennung komplett vergessen.
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

BlackJack hat geschrieben:[...]
Die Methode "funktioniert" ist relativ. Das da "<type 'bool'>" rauskommt ist "Zufall", es ist nirgends garantiert das die Zeichenkette so aussieht.
Oh, damit ist mein 3ter ansatz auch gescheitert.
Ich hatte mir gerade sowas Überlegt:

Code: Alles auswählen

if str(type(options[option])) == "<type 'bool'>":
    return self._is_bool(section, option)
elif isinstance(options[option], int):
    return self._is_int(section, option)
[...]
BlackJack hat geschrieben:[...]
Was für eine Möglichkeit gibt es noch um direkt nur auf den Type hin zu überprüfen? Oder kann man isinstance beibringen das er bool nicht zum Type int und long Zählt? xD
Du willst also das Python Dich belügt? ;-)
Naja, hast ja recht ^^ Ich will nur das mit python sagt ob die instance vom type bool ist und nur davon.
BlackJack hat geschrieben:[...]
Schau Dir mal `issubclass()` an.
Ja, daran habe ich auch schon gedacht aber das funtzt nur wenn als Argumente Klassen übergeben werden. Mit instancen geht das nicht.

Gibt es nciht sowas wie istinstancefromsubclass() ^^
Och meno, damit ist das Projekt gescheitert :-[
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

BlackJack hat geschrieben:Das `types` Modul ist in aktuellen Python-Versionen auch nicht mehr nötig, man kann direkt mit den Konstruktoren vergleichen:

Code: Alles auswählen

In [8]: type(True) == bool
Out[8]: True

In [9]: type(1) == bool
Out[9]: False
Allerdings gab's mal in alten Versionen soweit ich weiss `True` und `False` einfach als Namen für 1 und 0 und nicht als eigenständigen Typ. Da kann man eine saubere Trennung komplett vergessen.
Würde das den nicht für meine zwecke reichen?

Code: Alles auswählen

In [8]: type(True) == bool
Out[8]: True
Ich will ja nur wissen obs Bool ist (also ob True oder False vorhanden ist. 1 und 0 zähle ich wider zu int). Ich brauche nur die Garantie das Python da kein mist baut so wie bei...

Code: Alles auswählen

if str(type(options[option])) == "<type 'bool'>":
    return self._is_bool(section, option)
Kann ich mich darauf verlassen das es immer geht?
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

OK, habs getestet. Das scheint ja zu gehen:

Code: Alles auswählen

if type(options[option]) == bool:
    return self._is_bool(section, option)
elif isinstance(options[option], int):
    return self._is_int(section, option) 
Ich hoffe das Python das auch imer so einhält in den anderen Versionen :)

Danke euch für eure Hilfe :)

Thx & LG Xtra

EDIT: Perfekt :bigok: 1 und 0 erkennt er auch nicht als bool, sondern als int. Genauso wie es sein muss! Ich hoffe die ändern das nicht in einer späteren Version.
BlackJack

XtraNine hat geschrieben:EDIT: Perfekt :bigok: 1 und 0 erkennt er auch nicht als bool, sondern als int. Genauso wie es sein muss! Ich hoffe die ändern das nicht in einer späteren Version.
Nein das war ja früher so als Übergang von 1 und 0 zu einem richtigem `bool` Typ. Es soll in Zukunft sogar verhindert werden das man die Namen `True` und `False` anderen Objekten zuordnet. Folgendes am Anfang eines Moduls, kann lustige Auswirkungen haben:

Code: Alles auswählen

In [12]: True = False

In [13]: print True
False
Bei `issubclass()` hättest Du einfach die Klasse von dem Objekt benutzen können: ``isssubclass(the_truth.__class__, bool)``. Aber mit `type()` geht's ja auch.
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

OK, danke dann weiß ich bescheid :)

...

BTW: Das ist ja völlig Strange :lol:...

Code: Alles auswählen

In [12]: True = False

In [13]: print True
False
Ich bin immer wider von Pythons Art echt überacht xD

lg
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

XtraNine hat geschrieben:BTW: Das ist ja völlig Strange :lol:... [...]

Ich bin immer wider von Pythons Art echt überacht xD
Deswegen gibt es nun Warnungen/Fehler, wenn man versucht an None zuzuweisen.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

1. isinstance(x, bool) gibt für ints natürlich False zurück.
2. True und False lassen sich neu zuweisen, weil es viele alte Module gab, die das selber taten, als es noch keine Booleans gab. Nicht auszuschließen, dass das sich z.B. in 2.6 ändert.
3. "type(x) == int" ist unschön und schreit nach "type(x) is int"

my 2 ¢
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

@birkenfeld:
Hab ich mittlerweile mitgekriegt. Als ich das gemacht hatte war es Ziemlich Spät gewesen und hatte mir das dann für den nächsten tag notiert. Naja, ich hatte eine Simplen Fehler gehabt in der Reihenfolge ^^

Es muss natürlich so sein...

Code: Alles auswählen

if isinstance(option_value, bool):
    return self._str2bool(section, option)                        
elif isinstance(option_value, int):
    return self._str2integer(section, option)
und nicht so ;)

Code: Alles auswählen

if isinstance(option_value, int):
    return self._str2integer(section, option)
elif isinstance(option_value, bool):
    return self._str2bool(section, option)                        
Ist ja auch klar, da ja int auch bool abfängt ;) Ich hatte das alles ein wenig durcheinander gebracht gehabt.

Trotzdem danke für dein Hinweiß :)

LG Xtra
Antworten