Python コードのリファクタリング: if-else ステートメントまたは switch ステートメントが多すぎる

バックグラウンド

入力パラメータに従って構成オブジェクトのさまざまなプロパティに値を割り当てます

オリジナルの実装

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>

コードレビュー: そうでない場合は多すぎるため、保守と拡張が容易ではありません

最適化 1: 部分的に適用

functools.partial( func*args**keywords )

呼び出されると、位置引数args とキーワード引数Keywords を使用して呼び出されたfuncのように動作する新しい部分オブジェクトを返します。呼び出しにさらに引数が指定された場合、それらはargsに追加されます。他のキーワード引数が指定されている場合、それらは展開され、キーワードをオーバーライドします。

簡単に言うと、関数とその関数に必要なパラメータをクラス「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)

コードレビュー: そうでなければ少ない、保守が簡単、拡張が簡単

ただ、パラメータを読み込むのが少し不便です。複数のパラメータを読み込んだ場合はどうすればよいですか? もっと良い方法はありますか?

最適化 2: argparse 分析ツールを適用する

argparse モジュールは、コマンド項目オプションとパラメータ解析用の組み込み Python モジュールです。argparse モジュールを使用すると、ユーザー フレンドリーなコマンド ライン インターフェイスを簡単に作成できます。

argparse は、プログラマがモデルのパラメータを定義し、sys.argv を通じてコマンド ライン パラメータを解析するのに役立ちます。また、このモジュールはヘルプとユーザー マニュアルを自動的に生成し、ユーザーが無効なパラメーターをプログラムに渡したときにエラー メッセージを報告します。

argparse は 3 つのステップを定義します
(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の3つのコマンドラインモジュール(sys.argv、argparse、click)の詳しい説明_python

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

おすすめ

転載: blog.csdn.net/qq_19446965/article/details/129481466