需要设计模式建议

时间:2018-11-03 13:59:28

标签: python design-patterns command-line-arguments

我需要帮助段来美化此代码:) 方法defineAction将基于args调用Class。考虑到类的相似性,有一些方法可以概括这段代码。 预先感谢

主类

def defineAction(args):

    if args.classabc is not None:
        for host in config.getList('ABC', 'hosts'):
            class_abc = ClassABC(config.getConfigs('ABC', host), args.version[0], user, password)
            class_abc.action(args.classabc)

    if args.classxyz is not None:
        for host in config.getList('XYZ', 'hosts'):
            class_xyz = ClassXYZ(config.getConfigs('XYZ', host), args.version[0], user, password)
            class_xyz.action(args.classxyz)

    # ...

def main():

    parser.add_argument('--classabc', choices=['cmd'])
    parser.add_argument('--classxyz', choices=['cmd'])
    # ...
    args = parser.parse_args()
    defineAction(args)

子类

class ClassABC:
    def __init__(self, configs, user, password):
        self.hostConfigs = configs['host']
        self.host_username = user
        self.host_password = password

    def a_method(self):
        # This Method is equal in all subclasses
    def b_method(self):
        # This Method is different all subclasses

    def action(self, action):
        self.a_method()
        self.b_method()

        if action == 'cmd':
            self.execute_cmd()

配置文件

[ABC]
hosts=abc_host1
var_abc=value1

[XYZ]
hosts=xyz_host1,xyz_host2
var_xyz=value2

1 个答案:

答案 0 :(得分:0)

我正在假设开关是互斥的(在这种情况下,您确实要使用mutually exclusive argument group)。

您希望argparser操作设置 class 。如果您的命令行开关不需要任何参数,那么我将在此处使用action="store_const"

parser.add_argument(
    '--classabc', dest="class_", const=ClassABC,
    action="store_const")
parser.add_argument(
    '--classxyz', dest="class_", const=ClassXYZ,
    action="store_const")

在解析时,使用一个或另一个开关时,上述操作会将args.class_设置为ClassABCClassXYZ。为类提供类方法或属性,以确定要查看的配置节,请勿在其他位置对这些名称进行硬编码。

例如,如果两个类都具有config_section属性('ABC'设置为ClassABC'XYZ'设置为ClassXZY),则可以使用在创建实例的循环中使用该属性:

if args.class_:
    for host in config.getList(class_.config_section, 'hosts'):
        instance = args.class_(config.getConfig(class_.config_section, host), ...)

想法是不要基于args属性进行切换,您可以将其保留为argparse,因为它已经为您确定了不同的选项。

如果两个命令行开关都需要一个附加参数,则创建一个自定义Action subclass

class StoreClassAction(argparse.Action):
    def __call__(self, parser, namespace, values, **kwargs):
        setattr(namespace, self.dest, (self.const, values)

然后将其用作:

parser.add_argument(
    '--classabc', dest="class_", choices=['cmd'], const=ClassABC,
    action=StoreClassAction)
parser.add_argument(
    '--classxyz', dest="class_", choices=['cmd'], const=ClassXYZ,
     action=StoreClassAction)

现在将args.class_参数设置为(classobject, argumentvalue),因此您可以使用:

if args.class_:
    cls, action = args.class_
    for host in config.getList(cls.config_section, 'hosts'):
        instance = args.class_(config.getConfig(cls.config_section, host), ...)
        instance.action(action)