具有多个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加载,另一个用于新品牌新对象的创建?
我希望创建新的构造函数为类方法,这样的事情,你可以创建更多,如果你需要,或调整它,如果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"
谢谢,我已阅读过关于类方法和工厂的内容,但并未真正将两个和两个方面放在一起如何在这里应用。在你的回答结束后再多读几句,让我知道我认为这是一个干净而合乎逻辑的解决方案。我已更新我的问题以包含修订版本。 – iceblueorbitz
我其实正在尝试更接近于你在这里为不同类型的类所做的事情,我在那里修改过的代码并未真正应用或工作。我遇到的问题我无法理解 - 在您提供的代码中,new_from_json()中指的是什么?在代码中的这一点上,什么都没有被初始化,所以自我并不是指任何特定的对象,并且自我.__ dict__不会有效地工作?我错过了什么吗? – iceblueorbitz
@iceblueorbitz我会在最后为你添加一个例子,所以也许你可以看到它更好 –
具有额外的构造方法(使用'@ classmethod'装饰器),如[答案](http s://stackoverflow.com/a/45292417/2437514),是一个非常典型的Python成语。标准库中有很多例子(想到的是'dict.fromkeys()'方法)。使用'__init__'作为最常用或最期望的构造函数,并根据需要创建其他构造函数。所以我建议添加一个'from_json'方法。 –
嗨@ice,我已经检查了编辑的问题,如果你可能有建议,你应该问另一个问题,用新的问题,我的意思是,我的答案只解决你的主要和原始问题(对于Python 3,我的错误),如果你问一个新问题,并解决新问题(也是这个问题的一个链接),你会成功,我可以保证它发生在别人帮助之前。如果你问一个新的问题,请让我知道,请详细说明:),希望我能帮到更多 –