if语句太多了

时间:2015-07-31 14:27:40

标签: python if-statement conditional code-readability code-maintainability

我有一些话题需要讨论。我有一个包含24 if s / elif s的代码片段。 Operation是我自己的类,表示与Enum类似的功能。
这是一段代码:

if operation == Operation.START:
    strategy = strategy_objects.StartObject()
elif operation == Operation.STOP:
    strategy = strategy_objects.StopObject()
elif operation == Operation.STATUS:
    strategy = strategy_objects.StatusObject()
(...)

从可读性的角度来看,我有顾虑。最好将其更改为24个类并使用polymorphism?我不相信它会使我的代码可维护......从一方面来看,if非常清楚,并且不应该难以理解,另一方面,if太多了StartObject()

我的问题相当普遍,但是我用Python编写代码,所以我不能使用像switch这样的结构。

您怎么看?

更新

一件重要的事情是StopObject()StatusObject()strategy是构造函数,我想将对象分配给div { font-size:2vw} 引用。

6 个答案:

答案 0 :(得分:12)

您可以使用字典。字典存储引用,这意味着函数完全可以使用,如下所示:

operationFuncs = {
    Operation.START: strategy_objects.StartObject
    Operation.STOP: strategy_objects.StopObject
    Operation.STATUS: strategy_objects.StatusObject
    (...)                  
}

有一个默认操作以防万一,所以当你运行它时使用try except并处理异常(即相当于你的else子句)

try:
    strategy = operationFuncs[operation]()
except KeyError:
    strategy = strategy_objects.DefaultObject()

或者使用字典的get方法,如果找不到您提供的密钥,则可以指定默认值。

strategy = operationFuncs.get(operation(), DefaultObject())

请注意,在将它们存储在字典中时,不要包含括号,只需在调用字典时使用它们。这也要求Operation.START可以使用,但是应该是这种情况,因为您将其描述为类似于ENUM的类。

答案 1 :(得分:3)

Python等同于switch语句是使用字典。基本上,您可以像存储案例那样存储键,并且值将是针对该特定情况调用的值。因为函数是Python中的对象,所以可以将它们存储为字典值:

d[operation]()

然后可以按如下方式使用:

operation_dispatcher = {
    Operation.START: strategy_objects.StartObject,
    Operation.STOP: strategy_objects.StopObject,
}

或者更简洁:

try:
    strategy = operation_dispatcher[operation] #fetch the strategy
except KeyError:
    strategy = default #this deals with the else-case (if you have one)
strategy() #call if needed

这可能会比乱七八糟的if-else语句更好地扩展。请注意,如果您没有其他案件可以处理,则可以直接使用strategy = operation_dispatcher.get(operation, default) strategy() #call if needed 字典。

答案 2 :(得分:2)

您可以尝试类似this的内容。

例如:

def chooseStrategy(op):
    return {
        Operation.START: strategy_objects.StartObject
        Operation.STOP: strategy_objects.StopObject
    }.get(op, strategy_objects.DefaultValue)

像这样称呼

strategy = chooseStrategy(operation)()

此方法的好处是提供默认值(如最终的else语句)。当然,如果您只需要在代码中的某个位置使用此决策逻辑,则可以始终使用strategy = dictionary.get(op,default)而不使用该函数。

答案 3 :(得分:1)

您可以使用getattr

进行一些内省
 strategy = getattr(strategy_objects, "%sObject" % operation.capitalize())()

假设操作是“STATUS”,它将大写为“Status”,然后前置为“Object”,给出“StatusObject”。然后将在StatusObject上调用strategy_objects方法,如果此属性不存在,或者如果它不可调用,则会发生灾难性故障。 :)(即添加错误处理。)

字典解决方案可能更灵活。

答案 4 :(得分:0)

如果PDO等是可以清除的,你可以使用带有键的字典作为条件,使用值作为要调用的函数,例如 -

Operation.START

然后您可以执行此字典查找并调用函数,示例 -

d = {Operation.START: strategy_objects.StartObject , 
     Operation.STOP: strategy_objects.StopObject, 
     Operation.STATUS: strategy_objects.StatusObject}

答案 5 :(得分:-1)

这是一个使用词典完成的混蛋开关/案例:

例如:

# define the function blocks
def start():
    strategy = strategy_objects.StartObject()

def stop():
    strategy = strategy_objects.StopObject()

def status():
    strategy = strategy_objects.StatusObject()

# map the inputs to the function blocks
options = {"start" : start,
           "stop" : stop,
           "status" : status,

}

然后调用等效的开关块:

options["string"]()