2017-07-25 3 views
2

Ich habe eine Anwendung, die ich in Python2.7 baue, das so funktioniert, wie es ist, aber nicht sauber fühlt, noch ist es sehr explizit in dem, was passiert, wenn ich also eine Weile von dem Code weggehe, habe ich eine Es ist schwer, sich daran zu erinnern, wie es unter der Haube funktioniert, was offensichtlich nicht gut ist. Ich habe den Code überarbeitet und es scheint expliziter, aber nicht wirklich sauberer.Python Child Class mit mehreren Init-Methoden?

Ich versuche herauszufinden, die sauberste Möglichkeit, diese Klassen auf zwei verschiedene Arten zu initialisieren - 1) von einer benutzergenerierten Instanziierung (im Falle des Hinzufügens eines neuen Objekts von Grund auf neu während der Programmausführung), oder 2) vom Importieren der Historie eines Objekts (von einer vorherigen Programmausführung) aus JSON. Hier ist mein letzter Weg, um darüber zu gehen:

class Device(object): 
    def __init__(self, dev_type, preset_prefix, default_preset, 
       from_json=False, json_path=None, **device_attrs): 

    if not from_json: # otherwise set in child class __init__ 
     self.name = device_attrs['name'] 
     self.sn = device_attrs['sn'] 
     self.mfg = device_attrs['mfg'] 
     self.tech = device_attrs['tech'] 
     self.model = device_attrs['model'] 
     self.sw_ver = device_attrs['sw_ver'] 
     self.hours = 0 
    else: 
     self.hours = device_attrs['hours'] 

    self.type = dev_type 
    self.json = json_path 
    self.preset_prefix = preset_prefix 
    self.preset = default_preset 

class Monitor(Device): 
    def __init__(self, name, sn, mfg, tech, model, sw_ver, from_json=False, 
       json_path=None, **monitor_dict): 
     if from_json: 
      self.__dict__ = monitor_dict 
     device_properties = {'name': name, 'sn': sn, 'mfg': mfg, 'tech': tech, 
          'model': model, 'sw_ver': sw_ver} 
     monitor_dict.update(device_properties) 
     super(Monitor, self).__init__('monitor', 'user', 1, from_json, 
             json_path, **monitor_dict) 
     if cals: 
      self._init_cal_from_json(monitor_dict['cals']) 

Jetzt kann ich aus einer zuvor gespeicherten JSON initialisiert wird (aus diesem Objekt erzeugte, damit ich sicher sein kann, den Schlüssel/Wert-Paare korrekt sind):

my_monitor = Monitor(from_json=True, json_path=device_json_file, **device_json_dict)) 

Oder als neues Objekt von Grund auf:

my_monitor = Monitor('monitor01', '12345', 'HP', 'LCD', 
        'HP-27', 'v1.0') 

Dies ist ein wenig chaotisch scheint, aber immer noch besser als meine ursprüngliche Version, die keine Positionsargumente für das Kind hatte init (was es schwierig macht zu wissen, welche Daten übergeben werden müssen), es dauerte nur ** monitor_dict in der Hoffnung, dass es die richtigen Schlüssel/Wert-Paare enthielt. Allerdings scheint diese Methode, diese Argumente zu übernehmen und sie zu einem Diktat zusammenzufassen, seltsam zu sein, aber ich habe dies mehrfach überarbeitet und dies scheint der sauberste Weg zu sein, darüber zu handeln.

Ist dies der beste Weg, um ein Objekt auf verschiedene Arten zu initialisieren oder kann ich zwei separate init Funktionen erstellen, eine für das Laden von JSON, und eine für die Neuentwicklung von brandneuen Objekten?

+0

Weitere Konstruktor Methoden (mit der '@ classmethod' Dekorator), wie in der [Antwort unten] (http s: //stackoverflow.com/a/45292417/2437514), ist ein ziemlich typisches Python-Idiom. Es gibt eine Reihe von Beispielen in der Standardbibliothek (eine, die mir in den Sinn kommt, ist die 'dict.fromkeys()' Methode). Verwenden Sie '__init__' für den am häufigsten verwendeten oder am meisten erwarteten Konstruktor, und erstellen Sie nach Bedarf andere Konstruktoren. Daher schlage ich vor, eine 'from_json'-Methode hinzuzufügen. –

+0

Hallo @ice, ich habe die bearbeitete Frage überprüft, wenn Sie einen Vorschlag haben, sollten Sie wahrscheinlich eine andere Frage stellen, mit den neuen Problemen, meine ich, lösen meine Antwort nur Ihre Haupt- und ursprüngliche Frage (für Python 3, mein Fehler), wenn du eine neue Frage stellst, mit den neuen Problemen (und auch mit einem Link zu dieser Frage) wirst du Erfolg haben, ich kann garantieren, dass es vorher passiert ist, zu jemand anderem, dem ich helfe. Wenn Sie eine neue Frage stellen, lassen Sie mich bitte wissen, mit allen Details :), ich hoffe, ich könnte mehr helfen –

Antwort

1

Ich ziehe neue Konstrukteure als Klassenmethoden zu erstellen, so etwas wie dies, könnten Sie mehr erstellen, wenn Sie benötigen, oder es anpassen, wenn necesary: ​​

class Device(object): 
    def __init__(self, dev_type, preset_prefix, default_preset, json_path=None, **device_attrs): 


     self.name = device_attrs['name'] 
     self.sn = device_attrs['sn'] 
     self.mfg = device_attrs['mfg'] 
     self.tech = device_attrs['tech'] 
     self.model = device_attrs['model'] 
     self.sw_ver = device_attrs['sw_ver'] 
     self.hours = 0 

     self.type = dev_type 
     self.json = json_path 
     self.preset_prefix = preset_prefix 
     self.preset = default_preset 

class Monitor(Device): 


    @classmethod 
    def new_from_json(self, name, sn, mfg, tech, model, sw_ver, json_path=None, **monitor_dict): 
     self.__dict__ = monitor_dict 
     device_properties = {'name': name, 'sn': sn, 'mfg': mfg, 'tech': tech, 
          'model': model, 'sw_ver': sw_ver} 
     monitor_dict.update(device_properties) 
     super(Monitor, self).__init__('monitor', 'user', 1, 
             json_path, **monitor_dict) 

Als Beispiel:

class Parent(): 
    def __init__(self,some): 
     self.some = some 


class Object(Parent): 

    @classmethod 
    def new_from_dict(self,some): 
     Parent.__init__(self,some) 
     self.adress = {"Me": 123} 
     return self 

dann:

obj = Object.new_from_dict("ME") 
obj.adress 

{"Me": 123} 

obj.some 

"ME" 
+0

Vielen Dank, ich habe über Klassenmethoden und Fabriken vor gelesen, aber nicht wirklich zwei und zwei zusammen, wie zu Verwende es hier. Ein wenig zusätzliche Lektüre nach Ihrer Antwort hier hat mich, was ich denke, ist eine saubere, logische Lösung. Ich habe meine Frage aktualisiert, um eine überarbeitete Version hinzuzufügen. – iceblueorbitz

+0

Ich habe tatsächlich versucht, etwas näher an das, was Sie hier für eine andere Art von Klasse, die ich habe, wo mein überarbeiteter Code nicht wirklich anzuwenden oder zu arbeiten.Das Problem, das ich habe, das ich nicht verstehen kann - in dem Code, den du zur Verfügung gestellt hast, worauf bezieht sich selbs in new_from_json()? An diesem Punkt im Code wurde nichts initialisiert, also bezieht sich Selbst nicht auf ein bestimmtes Objekt, und das Selbst .__ dict__ würde nicht wirklich funktionieren? Fehle ich etwas? – iceblueorbitz

+0

@iceblueorbitz Ich werde am Ende ein Beispiel für Sie hinzufügen, also könnten Sie es vielleicht besser sehen –