寻找优雅的方式编写此代码

时间:2019-05-11 15:48:11

标签: python

我正在寻找一种编写此代码的优雅方法。 (Python 2.7)

下面的代码位于for循环中。当说status的起始item s2时,我需要它反复运行直到到达status s7

如果成功返回False,则它将停止并停留在该级别,并且循环继续到下一个item

我希望不要使用try:来避免使用异常。 True / False success布尔值足以满足此目的。如果您认为我应该另外考虑,请纠正我。

这是我尝试的代码。我正在尝试找到一种更优雅的解决方案。

def do_s1(): # similar for other status
  if condition:
    success = True
  else:
    success = False
  return success

for i in items:
  if status[i] = s1:
    success_s1 = do_s1()
    if success_s1:
      success_s2 = do_s2() 
      if success_s2:
        success_s3 = do_s3()
        # all the way until do_s7(), iteratively

  if status[i] = s2:
    do_s2()
    if success:
      do_s3() # all the way until do_s7(), iteratively
...

  if status[i] = s7:
    do_s7()
    # some code

每当成功变为False或达到s7时,循环应迭代到下一个项目

3 个答案:

答案 0 :(得分:1)

通常,我不建议仅将列表推导或生成器用于在列表的每个项目上执行函数的副作用。但是,在这里,它有可能极大地减少代码的大小。

首先将每个do_*函数放在一个列表中,然后将每个状态放在一个单独的列表中:

dos = [do_s1, do_s2, do_s3, do_s4, do_s5, do_s6, do_s7]
ss = [s1, s2, s3, s4, s5, s6, s7]

现在,我们将利用all函数的优势,该函数将消耗序列中的元素,直到找到一个错误的元素为止

for i in items:
    for j, s in enumerate(ss):
        if status[i] == s:
            all(f() for f in dos[j:])

就是这样。如果所有调用都返回all,则True返回True,但是您实际上对all的返回值不感兴趣,只是事实是它会立即停止评估函数因为其中之一返回False

但是,您可以用第三个显式循环替换对all的调用:

for f in dos[j:]:
   if not f():
       break

all在这里起作用是因为您的嵌套if语句可以简化为

  if status[i] == s1:
    success_s1 = do_s1()
    if success_s1:
      success_s2 = do_s2() 
      if success_s2:
        success_s3 = do_s3()
        # all the way until do_s7(), iteratively

if status[i] == s1:
    if do_s1() and do_s2() and ... do_s7():

使用and可以使各种do_*功能的评估在每一次失败时都会短路。

答案 1 :(得分:0)

您可以在do_s1函数中使用三元运算符:

return True if condition else False

由于我不知道状态 包含什么类型的变量以及s1,s2和s3是什么,因此其余代码有些混乱。

答案 2 :(得分:0)

我第二次推荐Giodo使用三元运算符。

您可以尝试在成功执行后通过调用下一个函数来结束do_s1()函数。然后,您不必显式地进行层次调用:

def do_s1(): # similar for other statuses
  success = True if condition else False
  if success:
    do_s2()

def do_s2():
  success = True if condition else False
  if success:
    do_s3()

...

if status[i] == s1:
  do_s1() # goes all the way up to s7

,如果您获得介于两者之间的其他状态,则顺序执行仍然有效:

if status[i] == s2:
  do_s2() # also goes until s7