(抱歉标题,部分问题是我对正确的关键字缺乏了解。)
我正在寻找以下问题的设计:
给定一个项目列表(具有不同的属性),根据显示的项目,我想运行不同的代码:
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",我需要将其转换为另一种语言中的相应操作。具体操作取决于变量的类型(例如,如果x
和y
是字符串或数字)和参数数量(例如,默认参数)。在大多数情况下,类型只在执行时才知道(例如,如果x
本身就是一个表达式,在这种情况下我使用递归来计算它)。函数的数量也很大,因此需要大量的elif
。
答案 0 :(得分:1)
以下是管理多个案例测试和操作以及减少elif
数量的解决方案提案。
该解决方案基于namedtuple
和简单的Parse
函数。
第1步 - 导入并声明namedtuple P_
。
from collections import namedtuple
P_ = namedtuple("Parser", ["len", "test", "action"])
"len"
用于管理if len(items) == 1:
,"test"
包含托管if A(items[0]):
,"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步 - 一系列“测试”功能(将由真实功能取代)
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