python代码重构:if-else过多或switch语句

背景

根据输入参数给config对象的不同属性赋值

原始实现

import sys
from dataclasses import dataclass


@dataclass
class Config:
    aaa: str = None
    bbb: str = None
    ccc: str = None
    ddd: str = None
    eee: str = None


def set_config_info(arg: str, value: str = None) -> Config:
    config = Config()
    if arg == '-a':
        config.aaa = value
    elif arg == '-b':
        config.aaa = value
    elif arg == '-c':
        config.aaa = value
    elif arg == '-d':
        config.aaa = value
    elif arg == '-e':
        config.aaa = value
    return config


def set_config_info2(arg: str, value: str = None) -> Config:
    """Python 3.10 """
    config = Config()
    match arg:
        case '-a':
            config.aaa = value
        case '-b':
            config.aaa = value
        case '-c':
            config.aaa = value
        case '-d':
            config.aaa = value
        case '-e':
            config.aaa = value
    return config


if __name__ == '__main__':
    if len(sys.argv) == 3:
        a = sys.argv[1]
        v = sys.argv[2]
        config_info = set_config_info(a, v)
    else:
        a = sys.argv[1]
        config_info = set_config_info(a)
    print('config_info:', config_info)

结果:

PS D:\MyPython\partial> python .\partial.py -a
config_info: Config(aaa=None, bbb=None, ccc=None, ddd=None, eee=None)
PS D:\MyPython\partial> python .\partial.py -a 111
config_info: Config(aaa='111', bbb=None, ccc=None, ddd=None, eee=None)
PS D:\MyPython\partial>

代码点评:if else过多,不好维护和扩展

优化1:应用partial

functools.partialfunc* args**关键字

返回一个新的部分对象,当被调用时,其行为类似于使用位置参数args 和关键字参数关键字调用的func。如果为调用提供了更多参数,则将它们附加到args。如果提供了其他关键字参数,则它们会扩展和覆盖关键字

简单说就是把一个函数,和该函数所需传的参数封装到一个class 'functools.partial'的类中,简化以后的调用方式

import sys
from functools import partial
from dataclasses import dataclass


@dataclass
class Config:
    aaa: str = None
    bbb: str = None
    ccc: str = None
    ddd: str = None
    eee: str = None


def set_value(obj, attr_name, value):
    setattr(obj, attr_name, value)


optdict = {
    '-a': partial(set_value, attr_name='aaa'),
    '-b': partial(set_value, attr_name='bbb'),
    '-c': partial(set_value, attr_name='ccc'),
    '-d': partial(set_value, attr_name='ddd'),
    '-e': partial(set_value, attr_name='eee'),
}


def set_config_info(arg: str, value: str = None) -> Config:
    config = Config()
    func = optdict.get(arg)
    func(config, value=value)
    return config


if __name__ == '__main__':
    if len(sys.argv) == 3:
        a = sys.argv[1]
        v = sys.argv[2]
        config_info = set_config_info(a, v)
    else:
        a = sys.argv[1]
        config_info = set_config_info(a)
    print('config_info:', config_info)

代码点评:if else少了,好维护,易扩展

但是参数读取有点不方便,读取多个参数又该怎么办?有没有更好的办法?

优化2:应用argparse解析工具

argparse 模块是 Python 内置的一个用于命令项选项与参数解析的模块,argparse 模块可以让人轻松编写用户友好的命令行接口。

argparse能够帮助程序员为模型定义参数、通过sys.argv 解析命令行参数。模块还会自动生成帮助和使用手册,并在用户给程序传入无效参数时报出错误信息。

argparse定义三步骤
(1)创建一个命令行解析器对象——创建 ArgumentParser() 对象

(2)给解析器添加命令行参数   ——调用add_argument() 方法添加参数

(3)解析命令行的参数              ——使用 parse_args() 解析添加的参
代码:

#!/usr/bin/python
from argparse import ArgumentParser


class Config(ArgumentParser):
    def __init__(self, description=None):
        super().__init__(description=description)
        self.add_argument("--aaa", "-a", default=None)
        self.add_argument("--bbb", "-b", default=None)
        self.add_argument("--ccc", "-c", default=None)
        self.add_argument("--ddd", "-d", default=None)
        self.add_argument("--eee", "-e", default=None)


if __name__ == '__main__':
    config_info = Config(description='config argv')
    print('config_info:', config_info.parse_args())

结果:

PS D:\MyPython\partial> python .\partial.py -a 111 -b 222 -c 333 -d 444 -e 555
config_info: Namespace(aaa='111', bbb='222', ccc='333', ddd='444', eee='555')

完结。。。是不是很丝滑,哈哈


参考:

https://www.cnblogs.com/YoungF/p/12047753.html

Python命令行解析器argparse详解-CSDN博客

详解python中的三种命令行模块(sys.argv,argparse,click)_python

https://www.cnblogs.com/angelyan/p/10791332.html

猜你喜欢

转载自blog.csdn.net/qq_19446965/article/details/129481466