Edit: Ich angegeben haben, sollte ich (fest) arbeiten w/Python 2, aber wäre daran interessiert zu sehen, wie diese entweder in Angriff genommen werden könnte 2 oder 3Magie Einfuhren in Python
Das Szenario: Ich habe ein Paket namens shapes
.
Ich habe ein Modul in shapes
namens factory
, die eine ShapeClassFactory
Klasse hat. Diese Klasse kann eine Zeichenfolge übergeben werden. Sie sucht in einer entfernten Datenbank nach Daten und verwendet diese, um eine Klasse dynamisch zu definieren, die zurückgegeben wird.
shapes.py:
from .factory import ShapeClassFactory
__all__ = ['ShapeClassFactory']
In der Praxis dieses Paket in einer Vielzahl von anderen Paketen verwendet werden kann & Skripte, etwa so:
from shapes import ShapeClassFactory
Circle = ShapeClassFactory("Circle")
Rect = ShapeClassFactory("Rect")
myCircle = Circle(r=5, fill='red')
mySquare = Rect(x=5, y=5, fill=None)
Das Problem: Die oben ist alles gut. Allerdings würde ich lieben das shapes
Paket so zu schreiben, um der Lage sein, die es wie so verwendet werden könnten:
from shapes import Circle, Rect
myCircle = Circle(r=5, fill='red')
mySquare = Rect(x=5, y=5, fill=None)
... die Idee ist, dass, wenn das Mitglied nicht in shapes
gefunden, es verwendet ShapeClassFactory
, um es zu versuchen und zu generieren.
Die Schwierigkeit besteht darin, dass die verfügbaren Klassen im Grunde nicht bekannt sind, bis sie angefordert werden, so dass eine vordefinierte Liste von Klassennamen nicht hilft.
Ich habe nichts dagegen werfen ImportError
wenn ShapeClassFactory
scheitert eine Klasse zu bauen - aber ist so etwas überhaupt möglich?
Die Importanweisung wird das Modul ausgeführt, das importiert wird, und dann die angeforderten Namen abrufen. Es gibt keine Möglichkeit vorher zu wissen, welche Namen angefordert werden. Im Prinzip können Sie das nicht tun, ohne etwas wie "__import__" (vielleicht mit Meta-Hooks) zu patchen, und das sollten Sie wirklich nicht tun. Zum Beispiel, was macht dir (shapes)? Der richtige Weg, dies zu tun, ist, was Sie bereits getan haben. –
Wenn die Anzahl der möglichen generierten Klassen ziemlich klein ist, können Sie alle im Namensraum von 'shapes' generieren. Dies wäre auch ein standardmäßiger und vernünftiger Weg, dies zu tun. –
Einer der Hauptgründe, warum ich generierte Klassen verwende, ist, dass ich das Paket nicht aktualisieren muss, wenn ein neuer Shape in der entfernten Datenbank definiert ist. Daher ist das Definieren einer Liste akzeptierter Klassen keine wirkliche Lösung. –