2016-12-31 82 views
0

(抱歉标题,问题的一部分,是我缺乏对正确的关键字的知识。)查找条件

我要寻找以下问题设计:

鉴于项目的列表(具有不同的属性),这取决于出现,我想运行不同的代码是什么物品:

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代码和后端代码)。

我怀疑我需要命名每个条件,并与他们构建一种树,但我没有找到正确的关键字搜索谷歌和SO。

这种类型的问题是如何解决的?

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

+0

是'A(项[0])'一些功能或'A() '只是为了检查'items [0]'的类型? –

+0

另外,C(项目)和D(项目)是否正确,或者你的意思是C(项目[0])和D(项目[1])? –

+0

@MoinuddinQuadri,对不起,我只是编辑了这个问题来澄清。不,A可以像递归评估表达式并确定其类型那样更复杂。 –

回答

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. 字段"action"包含函数指针作为return X(items)被执行,

步骤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 - 系列的 “测试” 功能(由以假乱真代替)

第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