针对长初始化方法的Python最佳实践

2024-04-27 13:25:01 发布

您现在位置:Python中文网/ 问答频道 /正文

我需要读取一个相当长的配置文件,配置设置大约为75(预计将来会有更多)

这导致了一个很长的初始化方法,感觉完全错误,看起来非常难看:

def __params_to_dict(self):
    config = {
        "general": {},
        "site": {"reference": {}},
        "routing": {},
        "sorting": {}, "junction_boxes": {},
        "table": {"tracker_config": {}}
    }

    config["general"]["client"] = self._client_name.get()
    config["general"]["location"] = self._project_location.get()

    config["site"]["ac_cable_fixed_correction"] = self._ac_fixed_allowance.get()
    config["site"]["ac_cable_variable_correction"] = self._ac_var_allowance.get()
    config["site"]["architecture"] = self.__get_architect_string()
    config["site"]["combiner_prefix"] = self._combiner_prefix.get()
    config["site"]["dc_cable_fixed_correction"] = self._conduit_fixed_allowance.get()
    config["site"]["dc_cable_variable_correction"] = self._conduit_var_allowance.get()
    config["site"]["dc_cable_fixed_correction"] = self._dc_fixed_allowance.get()
    config["site"]["dc_cable_variable_correction"] = self._dc_var_allowance.get()
    config["site"]["frequency"] = self._frequency.get()
    config["site"]["inverter_prefix"] = self._inverter_prefix.get()
    config["site"]["pcu_prefix"] = self._pcu_prefix.get()
    config["site"]["pf"] = self._power_factor.get()
    config["site"]["reference"]["x"] = self._reference_x.get()
    config["site"]["reference"]["y"] = self._reference_y.get()
    config["site"]["row_bearing"] = self._row_bearing.get()
    config["site"]["string_prefix"] = self._string_prefix.get()

    config["routing"]["seq"] = re.findall(r"\w+", self._sequence.get())
    config["routing"]["cables_per_conduit"] = self._cables_per_conduit.get()
    config["routing"]["corridor_offset"] = self._corridor_offset.get()
    config["routing"]["direct_to_jb"] = self._direct_to_jb.get()
    config["routing"]["down_pile_offset"] = self._down_pile_offset.get()
    config["routing"]["jb_setback"] = self._jb_setback.get()
    config["routing"]["straight_trench"] = self._straight_trench.get()
    config["routing"]["multi_trench"] = self._multi_trench.get()
    config["routing"]["seq"] = self._sequence.get()
    config["routing"]["trench_depth"] = self._trench_depth.get()

    config["sorting"]["block"] = self._blocks.get()
    config["sorting"]["even_inputs"] = self._even_inputs.get()
    config["sorting"]["even_jbs"] = self._even_jbs.get()
    config["sorting"]["fill"] = self._fill.get().lower()

    ...

显然很难阅读。我可以添加标识每个部分的注释,例如# general# site等等,但这也不会使它看起来更好。另一种选择是为单独的部分提供单独的函数,例如def __general_to_dictdef __site_to_dict()等等,但我最终还是会得到一个笨拙的类

最佳做法是什么

编辑:只是澄清一下,这里的前端是tkinter,所以我不能使用yaml.load()yaml.dump(),这会使它更干净。我需要对每个变量执行getset,因为它们是tkinter变量类eg StringVar()IntVar()的实例


Tags: toselfconfiggetprefixsitedcrouting
2条回答

以下是一些可能有用的数据格式的想法:

self._attr_paths = {
    "_client_name":         ["general", "client"],
    "_project_location":    ["general", "location"],
    "_reference_x":         ["site", "reference", "x"],
    "_reference_y":         ["site", "reference", "y"],
    "_sequence":            ["routing", "seq"],
    ...
}

self._attr_post_get = {
    "_sequence":            lambda x: re.findall(r"\w+", x),
    "_fill":                lambda x: x.lower(),
    ...
}

这些可用于以以下方式概括序列化:

def set_path(config, path, value):
    head, *tail = path
    if len(tail) == 0:
        config[head] = value
        return
    if head not in config:
        config[head] = {}            
    set_path(config[head], path, value)

def __params_to_dict(self):
    config = {}
    
    for attr, path in self._attr_paths.items():
        post_get = self._attr_post_get.get(attr, lambda x: x)
        value = post_get(getattr(self, attr))
        set_path(config, path, value)

当然,这是一个没有单一精确答案的问题。 我认为让你烦恼的是,你有一种复制的形式,配置和初始化是耦合和镜像的

可能值得尝试yaml配置文件,您可以使用PyYaml读入这些文件。在配置级别设置的结构将转换为字典,并保存各个读入。然后可以使用dunder init设置其他逻辑,例如根据某些字段的设置触发其他初始化

相关问题 更多 >