找到条件树满足的条件

时间:2016-12-31 08:20:20

标签: python

(抱歉标题,部分问题是我对正确的关键字缺乏了解。)

我正在寻找以下问题的设计:

给定一个项目列表(具有不同的属性),根据显示的项目,我想运行不同的代码:

if len(items) == 1 and A(items[0]):
    return X(items)
elif len(items) == 1 and B(items[0]):
    return Y(items)
elif len(items) == 2 and C(items) and D(items):
    return Z(items)
else:
    raise NotImplementedError

A, B, C, D可以像评估项目的类型一样简单,但它可能需要递归地评估表达式(例如items[0] = Expression("((x + y) - z)") is a string or a number?))。

到目前为止,我使用了elif吨。但正如您已经观察到的那样,有些条件会重复多次,并且代码难以阅读。

我尝试的第二件事是将第二个条件与第一个条件分开,例如

if len(items) == 1:
    if A(items[0]):
        return X(items)
    elif B(items[0]):
        return Y(items)
...

然而,即使某些条件对决策具有高度信息(例如len(items) == 1),因此使它们成为最外层条件也是有意义的,它们可以来自项目的非常不同的领域(例如UI的代码和后端代码)。

我怀疑我需要为每个条件命名,并用它们构建一种树,但我找不到用于在Google和SO中搜索它的正确关键字。

这种问题是如何解决的?

编辑:上下文:我正在实现它来解释脚本语言。基本上,当解释器遇到表达式时,例如, " x + y"或" x * y"或者"调用z",我需要将其转换为另一种语言中的相应操作。具体操作取决于变量的类型(例如,如果xy是字符串或数字)和参数数量(例如,默认参数)。在大多数情况下,类型只在执行时才知道(例如,如果x本身就是一个表达式,在这种情况下我使用递归来计算它)。函数的数量也很大,因此需要大量的elif

1 个答案:

答案 0 :(得分:1)

以下是管理多个案例测试和操作以及减少elif数量的解决方案提案。 该解决方案基于namedtuple和简单的Parse函数。

第1步 - 导入并声明namedtuple P_

from collections import namedtuple
P_ = namedtuple("Parser", ["len", "test", "action"])
  1. 字段"len"用于管理if len(items) == 1:
  2. 字段"test"包含托管if A(items[0]):
  3. 的函数指针列表
  4. 字段"action"包含要作为return X(items)执行的函数指针,
  5. 第2步 - 定义Parse()函数以分析输入列表items并在实施时执行action

    def Parse(m_struct, m_list):
        # explore all namedtuple P_
        for m_parse in m_struct:
            # check is the "len" parameter matches
            if len(m_list) == m_parse.len:
                # execute the list of "test" functions
                for m_test in m_parse.test:
                    if m_test(m_list) == False:
                        # at the first False => return
                        return
                # otherwise execute the action
                m_parse.action(m_list)
                return
        # to be replaced by a real 'raise NotImplementedError'
        print("raise NotImplementedError")
    

    第3步 - 定义要探索的namedtuple P_数组

    mParsers = [
        P_(len = 1, test = [ A ], action = X),
            # if len(items) == 1 and A(items[0]):
            #     return X(items)
        P_(len = 1, test = [ B ], action = Y),
            # elif len(items) == 1 and B(items[0]):
            #     return Y(items)
        P_(len = 2, test = [ C, D ], action = Z)
            # elif len(items) == 2 and C(items) and D(items):
            #     return Z(items)
    ]
    

    第4步 - 一系列“测试”功能(将由真实功能取代)

    def A(lst_items):
        return True
    
    def B(lst_items):
        return False
    
    def C(lst_items):
        return True
    
    def D(lst_items):
        return False
    

    第5步 - 一系列“动作”功能(由真​​实功能取代)

    def X(lst_items):
        print('X=>',lst_items)
        return
    
    def Y(lst_items):
        print('Y=>',lst_items)
        return
    
    def Z(lst_items):
        print('Z=>',lst_items)
        return
    

    第4步 - 如何调用解析器

    print("- list[1]")
    Parse(mParsers,[1])
    # output
    # - list[1]
    # X=> [1] ... action executed
    print("- list[1, 2]")
    Parse(mParsers,[1, 2])
    # output
    # - list[1, 2] ... 1 test is False = no action
    print("- list[1, 2, 3]")
    Parse(mParsers,[1, 2, 3])
    # output
    # - list[1, 2, 3]
    # raise NotImplementedError = Exception for a list of 3 items