Seite 1 von 1
Klasseninstanz aus String erzeugen: obj = "ClassN"
Verfasst: Montag 24. September 2007, 13:05
von ChrisGTJ
Hallo, ich noch mal.
bezugnehmend auf meinen anderen Thread
http://www.python-forum.de/viewtopic.php?p=78396#78396
ergibt sich eine weitere Frage:
Wir haben den Namen einer Klasse als String und möchten den Namen nun als Klasse behandelt sehen und eine Instanz davon erzeugen. Im Prinzip suche ich sowas wie ein annonymes getattr():
Code: Alles auswählen
class ClassN( object):
pass
obj = get_instance_from_name( "ClassN")
Gibt es sowas?
Gruß,
Christoph
Verfasst: Montag 24. September 2007, 13:19
von BlackJack
Klassen sind Attribute des Moduls in dem sie stecken. Also funktioniert das normale `getattr()` mit dem Modul. Immer dran denken: in Python ist alles ein Objekt.
Code: Alles auswählen
import motoren
motor = getattr(motoren, 'SuperMotor')()
Erzeugt einen `motoren.SuperMotor`.
Verfasst: Freitag 5. Oktober 2007, 13:36
von Jan-Peer
Hallo,
ich möchte den obigen Beitrag noch einmal aufgreifen: Ich habe ein Package, in dem sich eine beliebige Anzahl mir unbekannter Module befindet, in denen sich jeweils eine Klasse befindet. Klasse und Modul haben den selben Namen.
Das Package wird mit from package import * importiert.
Jetzt habe ich einen String (aus einer Datenbank), der den Namen der zu instanziierenden Klasse enthält.
getattr funktioniert mit dem Package nicht - wie kann ich jetzt an meine Instanz rankommen?
Vielen Dank
Jan-Peer
Verfasst: Freitag 5. Oktober 2007, 13:47
von Leonidas
Jan-Peer hat geschrieben:Jetzt habe ich einen String (aus einer Datenbank), der den Namen der zu instanziierenden Klasse enthält.
getattr funktioniert mit dem Package nicht - wie kann ich jetzt an meine Instanz rankommen?
Module mit Stern-Importen reinzuziehen ist fast immer eine schlechte Idee. Daher lass das lieber.
Wenn du dann den Klassennamen hast, ist das simpel:
Code: Alles auswählen
import package
getattr(getattr(package, 'Modulname'), 'Klassenname')
(ungetestet)
Verfasst: Freitag 5. Oktober 2007, 13:53
von helduel
Moin,
Jan-Peer hat geschrieben:[...]
Klasse und Modul haben den selben Namen.
Das Package wird mit from package import * importiert.
Jetzt habe ich einen String (aus einer Datenbank), der den Namen der zu instanziierenden Klasse enthält.
versuch mal:
Ob das 'from package import *' aber wirklich Sinn macht? Vielleicht wäre folgendes besser:
Code: Alles auswählen
module_name = '%s.%s' % (package, name)
module = __import__(module_name, globals(), locals(), [name])
cls = getattr(module, name)
Oder so ähnlich

.
Gruß,
Manuel
Verfasst: Freitag 5. Oktober 2007, 13:54
von Jan-Peer
Ist leider nicht ganz so einfach:
Code: Alles auswählen
>>> import campaigns
>>> getattr(getattr(campaigns, "Campaign"), "Campaign")
Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: 'module' object has no attribute 'Campaign'
Verfasst: Freitag 5. Oktober 2007, 13:59
von Leonidas
Kannst du denn auf ``campaign.Campaign`` im Interpreter zugreifen?
Verfasst: Freitag 5. Oktober 2007, 14:04
von Jan-Peer
@leonidas:
Nein, komischerweise auch nicht. Hab ich beim aufsetzen des Packages was falsch gemacht?
Verfasst: Freitag 5. Oktober 2007, 14:40
von Leonidas
Was gibt denn ``dir(campaign)`` aus? Da sind die meisten Namen auf die du zugreifen kannst (es kann durchaus mehr Namen geben, als ``dir()`` anzeigt, aber das ist selten).
Verfasst: Freitag 5. Oktober 2007, 16:04
von BlackJack
Zwei Fragen: Ist es überhaupt ein Package, also ist die `__init__.py` vorhanden? Und liegt das Package in `sys.path`?
Verfasst: Freitag 5. Oktober 2007, 17:19
von Jan-Peer
``dir()`` gibt builtins, doc, file, name und path aus
Die __init__.py ist vorhanden, wenn auch leer. Das Package liegt im Arbeitsverzeichnis, sollte also erreichbar sein. (Wenn ich direkt mit den Klassenamen arbeite, also campaigns.Campaign.Campaign(), geht es)
Verfasst: Freitag 5. Oktober 2007, 17:24
von Leonidas
Jan-Peer hat geschrieben:``dir()`` gibt builtins, doc, file, name und path aus
Du musst schon ``dir(campaign)`` machen (wie ich schon schrieb), sonst zeigt er dir den lokalen Namespace an, was eher uninteressant ist.
Verfasst: Freitag 5. Oktober 2007, 18:04
von Jan-Peer
Hab ich gemacht, war jetzt bloß zu faul, die paar Zeichen noch mit in die Klammern zu setzen. Sieht also eher unbefriedigend aus.
Aber vielleicht gibt es ja auch noch einen intelligenteren Ansatz für mein Problem:
Ich schreibe an einer Anwendung zur Verwaltung von Werbeaktionen. Es gibt eine abstrakte Klasse ("Campaign"), von der sich wiederum die eigentlichen Typklassen ableiten. Ich möchte das System möglichst offen halten, d.h. wenn ich einen neuen Aktionstyp einführe, möchte ich die benötigte Klasse im Idealfall einfach nur in ein bestimmtes Verzeichnis (hier kommt das Package ins Spiel) kopieren müssen. Ach ja: Irgendwie müsste sich dann auch noch eine Liste der verfügbaren Typen (= Klassennamen) erzeugen lassen.
Wenn jemand einen schöneren Ansatz kennt, darf er mich gerne auf den richtigen Pfad leuchten

Verfasst: Freitag 5. Oktober 2007, 18:30
von Leonidas
Jan-Peer hat geschrieben:Ich schreibe an einer Anwendung zur Verwaltung von Werbeaktionen. Es gibt eine abstrakte Klasse ("Campaign"), von der sich wiederum die eigentlichen Typklassen ableiten. Ich möchte das System möglichst offen halten, d.h. wenn ich einen neuen Aktionstyp einführe, möchte ich die benötigte Klasse im Idealfall einfach nur in ein bestimmtes Verzeichnis (hier kommt das Package ins Spiel) kopieren müssen. Ach ja: Irgendwie müsste sich dann auch noch eine Liste der verfügbaren Typen (= Klassennamen) erzeugen lassen.
Plugin-System?
What's on Air hat genau sowas.
Verfasst: Samstag 6. Oktober 2007, 11:30
von Jan-Peer
Besten Dank,
ich hab mich davon mal inspirieren lassen und eine mich zufriedenstellende Lösung gefunden.