具有多个init方法的Python子类?

问题描述:

我有一个应用程序,我正在Python2.7中工作,但不感觉干净,也不是很清楚发生了什么,所以如果我离开代码一段时间,我有一个很难记住它是如何在引擎盖下工作的,这显然不是很好。我重构了代码,它看起来更清晰,但并非真正的清洁。 (1)从用户生成的实例(在程序执行期间从头开始添加新对象),或者2)用户生成的实例从JSON中导入对象的历史记录(来自先前的程序执行)。这是我最新的要对这个办法:具有多个init方法的Python子类?

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']) 

现在我可以从以前保存的JSON初始化(从该对象产生的,所以我可以肯定的是键/值对是正确的):

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

或者作为一个从无到有的新对象:

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

这似乎有点乱,但还是比我原来的版本更好它不具有任何位置参数为孩子init(很难知道必须传入哪些数据),它只需** monitor_dict希望它包含正确的键/值对。然而,将这些参数合并为一个字典的方法似乎很奇怪,但我已经多次重构了这个,并且这似乎是最简单的方法。

这是以多种方式处理初始化对象的最佳方式,或者我可以以某种方式创建两个独立的init函数,一个用于从JSON加载,另一个用于新品牌新对象的创建?

+0

具有额外的构造方法(使用'@ classmethod'装饰器),如[答案](http s://*.com/a/45292417/2437514),是一个非常典型的Python成语。标准库中有很多例子(想到的是'dict.fromkeys()'方法)。使用'__init__'作为最常用或最期望的构造函数,并根据需要创建其他构造函数。所以我建议添加一个'from_json'方法。 –

+0

嗨@ice,我已经检查了编辑的问题,如果你可能有建议,你应该问另一个问题,用新的问题,我的意思是,我的答案只解决你的主要和原始问题(对于Python 3,我的错误),如果你问一个新问题,并解决新问题(也是这个问题的一个链接),你会成功,我可以保证它发生在别人帮助之前。如果你问一个新的问题,请让我知道,请详细说明:),希望我能帮到更多 –

我希望创建新的构造函数为类方法,这样的事情,你可以创建更多,如果你需要,或调整它,如果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) 

举个例子:

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 

那么:

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

{"Me": 123} 

obj.some 

"ME" 
+0

谢谢,我已阅读过关于类方法和工厂的内容,但并未真正将两个和两个方面放在一起如何在这里应用。在你的回答结束后再多读几句,让我知道我认为这是一个干净而合乎逻辑的解决方案。我已更新我的问题以包含修订版本。 – iceblueorbitz

+0

我其实正在尝试更接近于你在这里为不同类型的类所做的事情,我在那里修改过的代码并未真正应用或工作。我遇到的问题我无法理解 - 在您提供的代码中,new_from_json()中指的是什么?在代码中的这一点上,什么都没有被初始化,所以自我并不是指任何特定的对象,并且自我.__ dict__不会有效地工作?我错过了什么吗? – iceblueorbitz

+0

@iceblueorbitz我会在最后为你添加一个例子,所以也许你可以看到它更好 –