【问题标题】:Get which or-condition is met in an if-statement in Python获取 Python 中的 if 语句中满足哪个或条件
【发布时间】:2021-10-27 08:57:55
【问题描述】:

我有以下 Python if 语句:

if element1 in list[2] or element2 in list[2] or 3 in list[2]:
   do some more if-statements...
else:
   print something...

是否可以打印(或以某种方式获取)满足哪些或条件(如果有的话)?因为 if 子句中还有其他 if 语句,所以我不想使用三个不同的 if 语句,这将是一种解决方案。但这最终会出现在近 12 种不同的 if 语句中。我只想记录满足哪个条件以进行进一步分析。我当然搜索了谷歌,但没有找到任何东西。 提前致谢。

编辑: 用例:尝试使用“AND”和“OR”函数实现搜索算法。我敢肯定可以写得更好更干净,但现在算什么有效;-)

【问题讨论】:

  • Python 在使用 or 语句时会做这种神奇的事情,称为短路。这意味着如果第一个语句(在您的情况下 list[2] 中的 element1)为 True,则 if 中的其他语句将被忽略,因为它始终返回 True。因此,没有办法完全按照您的意愿行事。我建议首先按照 MadPhysicist 的建议对它们进行评估(如果您真的需要知道哪些值是 T/F)。

标签: python if-statement conditional-statements


【解决方案1】:

你可以这样做:

if element1 in list[2] or element2 in list[2] or 3 in list[2]:
    if element1 in list[2]:
        print('element1 found in list[2]')
    if element2 in list[2]:
        print('element1 found in list[2]')
    if element3 in list[2]:
        print('element1 found in list[2]')
    #=== do some more if-statements...
else:
   #== print something...

在分组的if 条件中,您可以检查实际满足了哪个条件。
我不知道有更好的方法来做到这一点。

【讨论】:

  • 你忘了在字符串周围加上''
  • 已更正,谢谢!
【解决方案2】:

您可以将布尔值分配给名称:

a = element1 in list[2]
b = element2 in list[2]
c = 3 in list[2]
if a or b or c:
    print(f"{element1} {'in' if a else 'not in'} list[2]")
    print(f"{element2} {'in' if b else 'not in'} list[2]")
    print(f"3 {'in' if c else 'not in'} list[2]")

但这消除了短路的任何好处,因为所有表达式都需要计算。

在 python 3.8+ 中你可以使用赋值表达式:

if (a := (element1 in list[2])) or \
   (b := (element2 in list[2])) or \
   (c := (3 in list[2])):
    try:
        print(f"{element1} {'in' if a else 'not in'} list[2]")
        print(f"{element2} {'in' if b else 'not in'} list[2]")
        print(f"3 {'in' if c else 'not in'} list[2]")
    except NameError:
        pass

请记住,这种方法有相反的问题:某些名称可能由于短路而未被分配。您不会知道任何名称超过第一个错误名称的结果。

如果你真的有很多条件,另一种方法是建立一个列表而不是命名每个单独的:

test = [element1, element2, 3]
x = [t in list[2] for t in test]
if any(x):
    for t, r in zip(test, x):
        print(f"{t} {'in' if r else 'not in'} list[2]")

你甚至可以使用集合:

test = {element1, element2, 3}
s2 = set(list[2])
x = test & s2
if x:
    print('{x!r} in list[2]')
    if y := test - x:
        print('{y} not in list[2]')

选择取决于您的具体用例。

【讨论】:

  • 感谢您的提示。您建议的列表解决方案似乎有效,并且还具有我可以定义列表中的元素的优点,这对整个代码非常有帮助(尝试使用“AND”和“OR”函数实现搜索算法)。即使我还没有完全理解代码... ;-)
  • 似乎有效,我想我现在理解了代码。只剩下一个问题了。在“x = [t in list[2] for t in test]”中搜索关键字是不应该区分大小写的。有没有办法解决这个问题?
  • @plategt。如果您确保list[2] 中的所有内容都是小写/大小写折叠,请将t in list[2]... 替换为t.casefold() in list[2]...
  • 谢谢。我实现了它,但我重新考虑了另一个问题。在我使用“列表中的元素”之前,这对于搜索来说更具可变性。使用新解决方案,如果我搜索“tiger”,它不会找到“tigers”。我需要确保如果出现该术语,即使前后都有字母,也能找到它。就像在搜索词周围使用 * 一样。您的建议似乎很容易解决小写问题。但是另一个呢?
  • @plategt。在这一点上,我建议对将str.__contains__ 之类的方法应用于每个元素进行一些研究(与您现在使用的list.__contains__ 相比)。甚至可能是正则表达式,但在这种情况下这可能是矫枉过正。当然超出了这一问题的范围。
【解决方案3】:

我认为您可以为此目的使用 Python 字典。举个例子:

list1=[list2,list2,list2]
list2=[3,4,6]
list3=[4,6,7]
element1=0
element2=0

if element1 in list1[2] or element2 in list1[2] or 3 in list1[2]:
  dict_conditions={"Condition 1":str(element1 in list1[2]),"Condition 2":str(element2 in list1[2]) ,"Condition 3":str(3 in list1[2])}
  print(dict_conditions)

这将打印以下输出:

{'Condition 1': 'False', 'Condition 2': 'False', 'Condition 3': 'True'}

【讨论】:

    【解决方案4】:

    如果您想要更简洁的代码,那么我建议将 if 语句检查放在一个函数中,并使用记录器来记录语句的真实性。

    import logging
    
    def elem_in_list(elem, list):
        if elem in list[2]:
            logging.info(f"{elem} is in list")
            return True
        logging.info(f"{elem} is not in list")
        return False
    
    if elem_in_list(element1, list) or elem_in_list(element2, list) or elem_in_list(element3, list):
        # do more if statements
    else:
        print(something)
    

    这可能是一种更简洁的方法,但据我所知,您无法使用大量 if 语句进行比较。

    【讨论】:

    • 感谢您的提示。想用这个作为简单的解决方案。由于提到的短路而不起作用。如果满足第一个条件,则不会再进行日志记录。不过,我必须测试每一条语句。
    【解决方案5】:

    这可以通过将每个条件的结果设置为名称/数字来非常简单地完成:

    >>> res = ((element1 in lst[2] and 1) or
    ...        (element2 in lst[2] and 2) or
    ...        (3 in lst[2] and 3))
    >>> if res:
    ...     print('condition', res, 'succeeded')
    ...
    condition 2 succeeded
    

    如果您使用的是 python >= 3.8,则可以将其包裹得更整齐,如下所示:

    if (res := (element1 in lst[2] and 1) or
               (element2 in lst[2] and 2) or
               (3 in lst[2] and 3)):
        print('condition', res, 'succeeded')
    

    如果没有一个条件为真,res 将是False,否则它将是任何一个条件成功的名称/编号。


    boolean expressions 的 python 参考中解释了这个工作的原因:

    表达式x and y首先计算x;如果 x 为假,则其值为 回来;否则,评估 y 并且结果值为 返回。

    因此,要使上述方法正常工作,名称/编号必须评估为真(因此请避免使用空字符串、零或任何 bool(n) 为假的内容)。

    【讨论】:

      【解决方案6】:

      如果我想利用短路,我可能会做这样的事情:

      创建一个具有已知起始值的condition 变量。然后创建一个包含所有条件的 else-if 链,如果布尔表达式的计算结果为 True,则为每个条件设置一个不同的 condition 变量值。然后,在 else-if 块之后创建一个 if 语句,用于检查 condition 变量的值是否已更改。

      condition = 0
      if (expression)==(expression):
          condition = 1
      elif (expression)==(expression):
          condition = 2
      elif (expression)==(expression):
          condition = 3
      
      if condition:
         # perform common actions here
         if condition == 1:
             print(f"Condition met was condition ONE!")
      

      您也可以在 else-if 块中执行任何特定于条件的代码,而不是在最后一个 if 块中执行它,如果您认为这样会更在你的情况下可读。

      您还可以将需要在多种情况下执行的通用代码移动到一个函数中。

      if (expression)==(expression):
          # case 1 code here
          common_code()
      elif (expression)==(expression):
          # case 2 code here
          common_code()
      elif (expression)==(expression):
          # case 3 code here
          # Maybe this one does not need to call common_code()? This solution is fairly flexible.
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-12-17
        • 1970-01-01
        • 2023-03-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多