Refatoração de código Python: muitas instruções if-else ou switch

fundo

Atribua valores a diferentes propriedades do objeto de configuração de acordo com os parâmetros de entrada

implementação original

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)

resultado:

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>

Revisão de código : muitos, caso contrário, não é fácil de manter e expandir

Otimização 1: Aplicar parcial

functools.partial( func , *args , **palavras-chave )

Retorna um novo objeto parcial que, quando chamado, se comporta como func chamado com argumentos posicionais args  e palavras-chave argumentos keywords . Se mais argumentos forem fornecidos para a chamada, eles serão anexados a args . Se outros argumentos de palavra-chave forem fornecidos, eles se expandirão e substituirão as palavras-chave .

Simplificando, é encapsular uma função e os parâmetros exigidos pela função em uma classe 'functools.partial' para simplificar chamadas futuras

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)

Revisão de código : menos se mais, fácil de manter, fácil de expandir

Mas é um pouco inconveniente ler parâmetros, o que devo fazer se ler vários parâmetros? Existe uma maneira melhor?

Otimização 2: Aplicar a ferramenta de análise argparse

O módulo argparse é um módulo Python integrado para opções de itens de comando e análise de parâmetros. O módulo argparse permite que as pessoas escrevam facilmente interfaces de linha de comando amigáveis.

argparse pode ajudar os programadores a definir parâmetros para modelos e analisar parâmetros de linha de comando por meio de sys.argv. O módulo também gera automaticamente ajuda e manuais do usuário e relata mensagens de erro quando os usuários passam parâmetros inválidos para o programa.

argparse define três etapas
(1) Criar um objeto analisador de linha de comando - criar um objeto ArgumentParser()

(2) Adicione parâmetros de linha de comando ao analisador - chame o método add_argument() para adicionar parâmetros

(3) Analisar os parâmetros da linha de comando - Use parse_args() para analisar o
código do parâmetro adicionado:

#!/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())

resultado:

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

fim. . . Não é suave como seda, haha


referência:

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

Explicação detalhada do analisador de linha de comando Python argparse - CSDN Blog

Explicação detalhada de três módulos de linha de comando em python (sys.argv, argparse, click)_python

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

Guess you like

Origin blog.csdn.net/qq_19446965/article/details/129481466