Mit base Konstruktor der Klasse als Fabrik in Python?
Ich bin mit der Basis-Konstruktor der Klasse, die als Fabrik-und Wechsel-Klasse in diesem Konstruktor/Fabrik, um die Auswahl der geeigneten Klasse-ist dieser Ansatz gut ist python der Praxis oder gibt es elegantere Möglichkeiten?
Habe ich versucht zu Lesen, Hilfe zu Metaklassen, aber ohne großen Erfolg.
Hier Beispiel von dem, was ich Tue.
class Project(object):
"Base class and factory."
def __init__(self, url):
if is_url_local(url):
self.__class__ = ProjectLocal
else:
self.__class__ = ProjectRemote
self.url = url
class ProjectLocal(Project):
def do_something(self):
# do the stuff locally in the dir pointed by self.url
class ProjectRemote(Project):
def do_something(self):
# do the stuff communicating with remote server pointed by self.url
Mit diesem code kann ich die Instanz erstellen von ProjectLocal/ProjectRemote über Basis-Klasse-Projekt:
project = Project('http://example.com')
project.do_something()
Ich weiß, dass die Alternative Möglichkeit ist der Einsatz von Gewebe-Funktion, wird wieder das class-Objekt basierend auf url, dann code sieht ähnlich aus:
def project_factory(url):
if is_url_local(url):
return ProjectLocal(url)
else:
return ProjectRemote(url)
project = project_factory(url)
project.do_something()
Ist mein Erster Ansatz, einfach nur Geschmackssache oder hat es einige versteckte Fallstricke?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich würde stick mit dem factory-Funktion-Ansatz. Es ist sehr standard-python-und leicht zu Lesen und zu verstehen. Sie könnte es machen, mehr Generika zu behandeln weitere Optionen in mehrere Möglichkeiten, wie durch die übergabe der Diskriminator-Funktion und eine Zuordnung der Ergebnisse zu Klassen.
Wenn das erste Beispiel funktioniert, es ist mehr durch Glück als durch design. Was, wenn Sie wollten eine
__init__
definiert, die in der Unterklasse?cls
argument.Sollten Sie nicht brauchen Metaklassen für diese. Werfen Sie einen Blick auf die
__neue__
Methode. Dies wird Ihnen erlauben, die Kontrolle zu übernehmen von der Erstellung des Objekts, anstatt nur die Initialisierung, und so geben ein Objekt Ihrer Wahl.Den folgenden links können hilfreich sein:
http://www.suttoncourtenay.org.uk/duncan/accu/pythonpatterns.html#factory
http://code.activestate.com/recipes/86900/
Zusätzlich, wie Sie mit neuen style-Klassen, mit __new__, das als factory-Funktion (und nicht in einer Basis-Klasse, eine separate Klasse besser ist) ist das, was erfolgt in der Regel (soweit ich weiß).
Einer factory-Funktion ist in der Regel einfacher (und viele andere Menschen haben bereits gebucht)
Darüber hinaus ist es nicht eine gute Idee, um die __Klasse__ - Attribut die Art und Weise, die Sie getan haben.
Ich hoffe, Sie finden die Antwort und die links hilfreich.
Alle das beste.
Ja, wie erwähnt von @scooterXL, Fabrik-Funktion ist der beste Ansatz in diesem Fall, aber ich mag zu beachten, ein Fall für Fabriken, die classmethods.
Betrachten Sie die folgende Klassen-Hierarchie:
Nun können Sie erstellen, die Basis-Objekte von config-dict und aus der config-Datei:
Aber auch, Sie können das gleiche tun mit ExtendedBase kostenlos:
So, in diesem classmethod Werk kann auch als Hilfs-Konstruktor.
Normalerweise habe ich ein separates factory-Klasse dazu. Auf diese Weise müssen Sie nicht haben, um Verwendung von meta-Klassen oder-Zuweisungen zu
self.__class__
Ich versuche auch zu vermeiden, die Kenntnis darüber, welche Klassen verfügbar sind, für die Schöpfung, in die Fabrik. Vielmehr habe ich alle verfügbaren Klassen registrieren sich selbst mit dem Werk während das Modul importieren. Die geben es Klasse und einige Informationen darüber, Wann wählen Sie diese Klasse, um das Werk (dies kann ein name, ein regex oder ein callable (z.B. eine Klasse Methode der Registrierung der Klasse)).
Funktioniert sehr gut für mich und implementiert auch solche Dinge wie Kapselung und information hiding.
Ich denke, dass der zweite Ansatz über eine factory-Funktion ist viel sauberer als die Implementierung der Basisklasse hängt von deren Unterklassen.