Python 需要设计模式建议吗

Python 需要设计模式建议吗,python,design-patterns,command-line-arguments,Python,Design Patterns,Command Line Arguments,我需要帮助来美化这个代码:) 方法DefineAction将基于参数调用一个类。考虑到类的相似性,有一些方法可以概括这段代码。 提前谢谢 主类 def defineAction(args): if args.classabc is not None: for host in config.getList('ABC', 'hosts'): class_abc = ClassABC(config.getConfigs('ABC', host), ar

我需要帮助来美化这个代码:) 方法DefineAction将基于参数调用一个类。考虑到类的相似性,有一些方法可以概括这段代码。 提前谢谢

主类

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

我假设这些开关是互斥的(在这种情况下,您真的希望使用一个)

您希望argparser操作设置该类。如果您的命令行开关不需要接受任何参数,那么我会在这里使用
action=“store\u 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
设置为
ClassABC
ClassXYZ
。给类一个类方法或属性来确定要查找的配置部分,不要在其他任何地方硬编码这些名称

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

if args.class_:
    for host in config.getList(class_.config_section, 'hosts'):
        instance = args.class_(config.getConfig(class_.config_section, host), ...)
这样做的目的是不基于
args
属性进行切换,您可以将其留给
argparse
,因为它已经为您确定了不同的选项

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

然后将其用作:

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)

参数是独占的,还是可以同时使用
--classabc
--classxyz
两个参数?它们只在调用过程中单独使用,永远不会同时使用。您的示例使用
选项=['cmd']
,对于所有
--class*
开关,这是否总是相同的单字符串选项?或者这会有所不同?命令行开关会是什么样子,现在必须使用
--classabc cmd
--classxyz cmd
(不允许使用其他版本)。这里的实际规则是什么,对于
--class*
开关是否总是需要一个参数?这将定义子类中某些方法的行为,并且只传递一个值,或者在限制中传递一个dict。编辑:我更改了示例子类编辑:我添加了配置文件,包含操作及其主机的信息。我不知道这些信息将如何传递给类并由it@tiago:给
ClassABC
一个属性
config_section
并将其设置为
'ABC'
,对
ClassXYZ
执行相同操作,但将属性设置为
'XYZ'
。然后使用该属性读取正确的配置部分。
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)