Python3.dataclass与配置文件

Python3.dataclass与配置文件

dataclass是Python3.7新增的标准库dataclasses的装饰器,可自动生成__init__()等方法,支持类型提示。

yaml是常用的配置文件格式,语法比json更简洁,支持时间格式,在Python中通过第三方库PyYAML进行读写。

用dataclass组织配置文件信息,比用字典更便于程序的后续开发。

动机

对于Python而言,写程序的本质其实是程序员通过代码指导解释器工作。

配置信息通常是键值对形式,用字典表示很自然,但是有个问题:解释器并不知道字典都有哪些“键”。字典像是一个不提供菜单的饭店,老客户点对菜名才有得吃,相对而言,用类去组织配置信息虽然准备工作多一点,但亮出菜单后,点菜就方便很多。

本文简单介绍读取yaml配置文件,以及如何用dataclass组织配置信息。

yaml配置文件

config.yaml文件内容如下:

w: 70
e: 140
s: 0
n: 60
res: 0.5
time: 2022-09-25 00:00:00

则读取方式为:

import yaml

with open('./config.yaml') as f:
    config = yaml.load(f, Loader=yaml.FullLoader)

config字典为:

{'w': 70,
 'e': 140,
 's': 0,
 'n': 60,
 'res': 0.5,
 'time': datetime.datetime(2022, 9, 25, 0, 0)}

可以看到,时间直接解析成了datetime类型。

yaml不细讲了,其详细语法以及更多特性可以自行搜索。

dataclass

config字典得通过如config['w']的形式调用各配置项,方括号和引号打起来麻烦不说,要是打错配置名了在IDE也没有任何提示。如果用类重新组织config内容可以这么做:

class Config(object):
    def __init__(self, config):
        self.w = config['w']
        self.e = config['e']
        self.s = config['s']
        self.n = config['n']
        self.time = config['time']

config = Config(config)

那么接下来就可以通过如config.w的形式调用各配置项,比字典省去方括号和引号,并且在IDE中按下.的时候会出现候选,若是打错配置名也会出现提示。

这个类若是用dataclass实现则是这样:

from dataclasses import dataclass

@dataclass
class Config:
    w: int
    e: int
    s: int
    n: int
    res: float
    time: int

config = Config(**config)

效果完全相同但是更简洁了,不用手写__init__()了。

你可能发现time: int似乎不太对劲,type(config.time)返回的仍然是datetime.datetime,这涉及到Python的类型提示并不实际影响数据类型,因为Python仍是弱类型,这个类型提示是给程序员和IDE看的。

所以time: int改成time: datetime会更合理(要事先from datetime import datetime)。用上合理的类型提示会发生一件事:当你在IDE中输入config.time.,下拉提示就是包含strftimedatetime.datetime类型特有方法。

在这里插入图片描述

__post_init__()

dataclass支持一种特殊方法__post_init__(),会在自动生成的__init__()被调用中的最后自动被调用,相当于在自动生成的__init__()上做补充。

from datetime import datetime
from dataclasses import dataclass, field

import numpy as np

@dataclass
class Config:
    w: int
    e: int
    s: int
    n: int
    res: float
    time: datetime
    lon: np.ndarray = field(init=False)
    lat: np.ndarray = field(init=False)

    def __post_init__(self):
        w, e, s, n = self.w, self.e, self.s, self.n
        res = self.res
        assert -180 <= w < e <= 180 and -90 <= s < n <= 90
        self.lon = np.linspace(w, e, int((e - w) / res))
        self.lat = np.linspace(s, n, int((n - s) / res))

config = Config(**config)

这个例子中,__post_init__()做了两件事:

  1. w, e, s, n的合法性检验,保证其是合法经纬度范围。
  2. 生成了经纬度向量。lon: np.ndarray = field(init=False)表示lon这个属性不是__init__()初始化过程中产生的,所以不需要传给自动生成的__init__(),该例中在__post_init__()中被赋值。

总结

通过装饰器dataclass可以简化多属性类的编写,本文仅介绍了我认为很实用且便于表述的一种应用,实际上dataclass的功能、参数还有很多没有讲,比如默认值、字符串形式、比较方式、给__post_init__()传参等等,读者可在Python官网上查到详细的文档。

回到dataclass用于配置文件组织这个具体问题上,可拓展的细节还有:

  1. 多层级配置信息的情况下,每个被嵌套的配置层级都需要编写对应的dataclass。用类组织信息本来就不是最便于实现的,只是(我目前认为)最合理规范的,dataclass的角色是简化实现方式。
  2. 想把解析yaml的过程放到类似__post_init__()过程中,但那样自动生成的__init__()有点脱裤子放屁的感觉,还不如手写普通class,有待研究。
  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python配置文件通常使用YAML (.yml)格式。YAML是一种人类可读的数据序列化格式,用于表示数据结构和配置。在Python中,可以使用yaml库来解析和读取YAML格式的配置文件。以下是一个示例代码片段,展示了如何读取一个YAML配置文件并打印其中的内容: ```python import os import yaml # 获取yaml文件路径 yamlPath = os.path.join("D:\\test\\", "config.yml") # 打开并读取yaml文件 with open(yamlPath, 'r', encoding='utf-8') as f: cfg = yaml.safe_load(f) # 读取配置文件中的内容 user_name = cfg['user_name'] plan_date = cfg['date'] if 'date' in cfg else '' user_name_list = cfg['user_name_list'] # 打印配置文件中的内容 print(user_name) print(plan_date) for element in user_name_list: print(element.get('user_name')) ``` 以上代码使用yaml库的`safe_load`方法来加载YAML配置文件,并将其转换为Python字典对象。然后,可以通过字典的键来访问配置文件中的不同配置项。在这个例子中,我们将`user_name`、`date`和`user_name_list`的值打印出来。 请注意,你需要根据实际的配置文件路径和键名进行相应的修改。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [python解析yml配置文件](https://blog.csdn.net/godloveleo9527/article/details/123046694)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值