Seite 1 von 1

Auf user-defined class prüfen...

Verfasst: Montag 8. August 2011, 22:15
von mutetella
Hallo,

wie lässt sich überprüfen, ob ein Exemplar von einer user-defined class stammt?

Code: Alles auswählen

class Test(object):
    def __init__(self):
        pass

Code: Alles auswählen

>>> t = Test()
>>> not isinstance(t, (int, float, long, str, tuple, .....))
Das kann's ja wohl nicht sein... :)

Die Doku spricht an verschiedenen Stellen von built-in types und user-defined classes. Wie ich allerdings prüfen kann, ob ein Objekt eben kein built-in type ist, das konnte ich nicht finden.

mutetella

Re: Auf user-defined class prüfen...

Verfasst: Montag 8. August 2011, 23:21
von cofi
Wenn, dann ``issubclass``. Und der Ansatz erwischt auch alle ``class myInt(int): pass``.

Eine Moeglichkeit waere es, Attribute zu setzen und einen `TypeError` abzufangen. Man muss dabei aber aufpassen, dass man keine Namen ueberschreibt also schon mit dem jeweiligen `__dict__` abgleichen.

Aber um Himmels willen: Warum brauchst du das?

Re: Auf user-defined class prüfen...

Verfasst: Montag 8. August 2011, 23:24
von pillmuncher

Code: Alles auswählen

>>> (42).__class__ in vars(__builtins__).values()
True

Re: Auf user-defined class prüfen...

Verfasst: Dienstag 9. August 2011, 06:35
von snafu
Die im Modul types definierten Namen dürften so ziemlich alles an Builtin-Typen abdecken. Leider existiert dort kein `__all__` oder eine ähnliche "zentrale Stelle", die man nutzen könnte, so dass man die Typen selbst einsammeln muss:

Code: Alles auswählen

import types
builtin_types = [cls for (name, cls) in vars(types).items() if name.endswith('Type')]
Das dürfte immer funktionieren, da laut Doku die Namen grundsätzlich auf `Type` enden.

Da du ja offenbar vererbte Typen ausschließen willst, solltest du natürlich kein `isinstance()` nutzen, sondern den dem Konzept von Python zuwiderlaufenden exakten Typcheck nutzen:

Code: Alles auswählen

def is_builtin_type(instance):
    return type(instance) in builtin_types
//edit: Huch, es soll ja gerade *kein* Builtin-Typ sein. :o

Aber eigentlich ist die Funktion ja trotzdem noch okay:

Code: Alles auswählen

if not is_builtin_type(instance):
    [...]
Wobei ich gerade sehe, dass das Modul in Python 3.x umgebaut wurde und die direkt erreichbaren Standard-Typen rausgeschmissen hat. :(

Trotz alledem: Wozu brauchst du das? Ich bin fast sicher, dass das, was du vorhast (egal, was es ist), auch anders lösbar ist. ;)

Re: Auf user-defined class prüfen...

Verfasst: Dienstag 9. August 2011, 09:11
von mutetella
Wenn ich Euch jetzt sage, wozu ich das brauche, wird sicherlich gleich ein Sturm der Entrüstung über mir hereinbrechen... :D
Ok, ich hab' eine 'Observable()', deren Rückruffunktionen ich samt dazugehörige Parameter übergebe:

Code: Alles auswählen

class Test(object):
    def __init__(self):
        self.a = 1
        self.b = 2

def test():
    return 5, 6

def callback(a, b):
    print a, b

Code: Alles auswählen

>>> t = Test()
>>> o = Observable()
>>> o.add_observer(callback, (t, 'a'), (t, 'b'))
>>> o.add_observer(callback, (3, 4))
>>> o.add_observer(callback, (test,))
>>> o.notify_observers()
>>> 1, 2
>>> 3, 4
>>> 5, 6
Ihr könnt' Euch sicher denken, woran ich festhänge: 'add_observer' überprüft zunächst, ob das erste Element callable ist. Wenn nicht, kann es sich entweder um ein Exemplar mit Attribut (t, 'a') oder um feste Parameter (3, 4) handeln.
Nachdem nun sowohl 't' wie auch '3' nicht callable sind aber nur 't' ein Attribut 'a' hat, '3' aber kein Attribut '4', habe ich das erstmal mit 'try: ... except (TypeError, AttributeError):' gelöst.

'try: ... except: ...' mutet mir aber immer etwas wie ein Hack an, deshalb war ich auf der Suche nach einer Möglichkeit, 't' von '3' klar unterscheiden zu können.

mutetella

Re: Auf user-defined class prüfen...

Verfasst: Dienstag 9. August 2011, 09:43
von frabron
mutetella hat geschrieben: 'try: ... except: ...' mutet mir aber immer etwas wie ein Hack an, deshalb war ich auf der Suche nach einer Möglichkeit, 't' von '3' klar unterscheiden zu können.
Zumindest ist EAPF ein, wenn nicht der, empfohlener Programmierstil in Python, deshalb verstehe ich nicht, wieso dir das wie ein "Hack" vorkommt :?:

Re: Auf user-defined class prüfen...

Verfasst: Dienstag 9. August 2011, 09:58
von snafu
Dann mach doch das, was du beschrieben hast: Prüfung auf Aufrufbarkeit(`try...except` oder Bultin-Funktion `callable()`), ansonsten teste es als Attribut (`hasattr()`) und als letzte Lösung gibst du das Argument unverändert zurück.

Re: Auf user-defined class prüfen...

Verfasst: Dienstag 9. August 2011, 11:00
von lunar
@mutetella: Ich würde sagen, Du wiederholst Deine Fehler, und versuchst wieder, ein Objekt bzw. eine Funktion zu entwerfen, die einfach zu viel macht. Gerade die Attributerkennung ist viel zu magisch.

"add_observer()" sollte ohne Überprüfung eine aufrufbare Funktion entgegen nehmen, und nicht versucht zu erraten, was die Argumente sonst noch bedeuten könnten. Der Aufrufer kann ja immer noch eine lokale oder partielle Funktionen oder einen Lambda-Ausdruck übergeben, um beispielsweise Attribute zu setzen. Statt "o.add_observer(callback, (3, 4))" also einfach "o.add_observer(partial(callback, 3, 4))" und schon wird die ganze Magie und damit das ganze Problem hinfällig.

Re: Auf user-defined class prüfen...

Verfasst: Donnerstag 11. August 2011, 10:30
von mutetella
@lunar:
Du hast Recht, das ist immer wieder die Falle, in die ich tappe. Zuerst schreibe ich eine einfache Funktion, die 'irgendwas' bekommt, was damit macht und dann wieder ausspuckt. Dann kommt der Punkt, an dem dieses 'irgendwas' auch 'was anderes' sein könnte. Ab hier beginnt dann der Wahnsinn dieser 'if-else-achja, und wenn-dann'-Abfragerei.
Und das alles motiviert sich aus der Vorstellung, dass irgendwann einmal irgendwer diese Funktion ebenfalls gebrauchen könnte und sie deshalb möglichst breit und tolerant angelegt sein sollte.
Nicht selten muss ich mich dann selbst dabei bremsen, nicht noch Funktionalitäten zu implementieren, die ich selbst überhaupt nicht brauche...

Jetzt mal ehrlich: Sind eure Funktionen immer gänzlich trocken und zweckgebunden? Oder steht ihr hin und wieder auch in der Versuchung, da noch was cooles zu machen, das letztlich purer Luxus ist?

mutetella

Re: Auf user-defined class prüfen...

Verfasst: Donnerstag 11. August 2011, 10:55
von CM
So gut wie nie - ich wüßte schon gar nicht, wie ich nicht genutzte Funktionalität vernünftig warten könnte. Wenn Funktionen zusätzliche Optionen beherrschen sollen, bekommen sie halt eben das: Extraoptionen, die per default nicht gesetzt sind.

Was aber manachmal vorkommt ist so was:

Code: Alles auswählen

import numpy

def foo(iterable, ...):
    iterable = numpy.array(iterable) # hier kann natürlich eine Liste ihren Typ wechseln und zum numpy-array konvertieren
    ...
Wobei gerade diese Anwendung eigene Fallstricke bereit hält (schließlich können auch z. B. Strings in numpy-arrays umgewandelt werden, obwohl die Funktion wahrscheinlich nichts damit anfangen könnte), aber das ist eine Frage, der sich andere Paradigmen widmen. Gaaanz selten prüfe ich vorher mittels isinstance().