嵌套的 If/Else 控制流在不应该执行时被执行 - 可能是逻辑操作错误

Posted

技术标签:

【中文标题】嵌套的 If/Else 控制流在不应该执行时被执行 - 可能是逻辑操作错误【英文标题】:Nested If/Else control flow being executed when it shouldn't be - logical operations error probably 【发布时间】:2012-08-13 23:59:32 【问题描述】:

我有这个代码:

def time24hr(tstr):

    if ('a' and ':') in tstr:
        if tstr[:2] == '12':
            tstr = tstr.replace('12', '00').replace(':','').replace('am','hr')
            return tstr

        elif len(tstr[:tstr.find(':')]) < 2:
        # If length of string's 'tstr' slice (that ends before string ':') is less than 2
            tstr = tstr.replace(tstr[:tstr.find(':')],'0' + tstr[:tstr.find(':')]).replace(':', '').replace('am','hr')
            # Replace one-character string with combination of '0' and this one-character string. Then remove colon, by replacing it with lack of characters and replace 'am' string with 'hr'.
            return tstr

        else:
            tstr = tstr.replace(':', '').replace('am', 'hr')
            return tstr

    elif ('p' and ':') in tstr:
        tstr = tstr.replace(':', '').replace('pm', 'hr')
        return tstr

    else:
        return "Time format unknown. Type correct time."

当我执行此代码 print time24hr('12:34am') 时,它会返回应有的 0034hr 字符串。 它也适用于此print time24hr('2:59am'),返回0259hr。但是当我在其中输入带有12 的字符串时,它会自动省略这部分代码if ('a' and ':') in tstr:elif ('p' and ':') in tstr: 并继续到这部分:

if tstr[:2] == '12':
    tstr = tstr.replace('12', '00').replace(':','').replace('am','hr')
    return tstr

所以无论我输入12:15am 还是12:15pm,这段代码如果在字符串中找到12,就会开始执行上面的代码。 print time24hr('12:15pm') 返回 0015pm 但应该返回 0015hr 并且仅适用于其中包含 am 的字符串。否则,不要将12 更改为00 并返回,即1244hr12:44pm

我的问题是,为什么那些逻辑检查 if ('a' and ':') in tstr:elif ('p' and ':') in tstr: 不起作用? 此代码旨在成为此测验的解决方案 -> http://www.pyschools.com/quiz/view_question/s3-q8

================================================ ====================================

感谢您帮助我进行逻辑运算。

另外,我已经完成了上面提到的测验,下面是工作代码:

def time24hr(tstr):

    if (len(tstr[:tstr.find(':')]) == 2) and (tstr[0] == '0'):
        tstr = tstr.replace(tstr[0], '')

    if ('a' in tstr) and (':' in tstr):
        if tstr[:2] == '12':
            tstr = tstr.replace('12', '00').replace(':', '').replace('am', 'hr')
            return tstr

        elif len(tstr[:tstr.find(':')]) < 2:
        # If length of string's 'tstr' slice (that ends before string ':') is less than 2
            tstr = tstr.replace(tstr[:tstr.find(':')], '0' + tstr[:tstr.find(':')]).replace(':', '').replace('am', 'hr')
            # Replace one-character string with combination of '0' and this one-character string. Then remove colon, by replacing it with lack of characters and replace 'am' string with 'hr'.
            return tstr

        else:
            tstr = tstr.replace(':', '').replace('am', 'hr')
            return tstr

    elif ('p' in tstr) and (':' in tstr):
        if tstr[:2] == '12':
            tstr = tstr.replace(':', '').replace('pm', 'hr')
            return tstr

        elif len(tstr[:tstr.find(':')]) < 2:
            PmDict = '0':'12','1':'13', '2':'14', '3':'15', '4':'16', '5':'17', '6':'18', '7':'19', '8':'20', '9':'21', '10':'22', '11':'23'
            tstr = tstr.replace(tstr[:tstr.find(':')], PmDict[tstr[:tstr.find(':')]]).replace(':', '').replace('pm', 'hr')
            # Replace every "number" (which is string literally) with it's corresponding "number" in 24HR format, found in 'PmDict' dictionary. Then, as in above cases, remove colon ':' by replacing it with lack of character or space and then replace 'pm' with 'hr'
            return tstr

    else:
        return "Time format unknown. Type correct time."

我没有根据 KISS 规则编写此代码,如您所见 - 因为它有点复杂,但在 IMO 中运行得很好。

可以在这里测试-> http://doc.pyschools.com/console

大家干杯,感谢您的帮助:)

【问题讨论】:

因为这不是and 运算符的工作方式。它评估其操作数并返回确定最终结果的操作数。 'a' and ':'':',因为('a'':')都计算为 True0 and 'foo' 将导致 0,因为 0 的计算结果为 False。然后将结果传递给in 运算符,因此您得到':' in tstr 只是对@FelixKling 的评论稍作澄清:它不一定评估两个操作数。如果左操作数为真,它只评估右操作数。 (这被称为short circuit evaluation 【参考方案1】:
if ('a' and ':') in tstr:

相同
if ':' in tstr:

希望这能让您深入了解问题似乎是什么。

可能替换为

if 'a' in tstr and ':' in tstr:

【讨论】:

为什么'a' and ':' 评估为: @arxanas -- 因为非空字符串是真实的。 and 操作员看着左边的对象并问——这像真的吗?如果不是,则返回左侧对象。如果左边的对象是 true-like,则返回右边的对象。 @arxanas 同样,'a' or ':' 的计算结果为 'a' 如果可行,则将其标记为答案,然后问题将被标记为已解决 好的,我想出了正确的想法并提出了解决方案。解决方案在上面更新的问题中。干杯!【参考方案2】:

你的第一次检查:

('a' and ':') in tstr

只是真正检查 ':' 是否在 tstr 中。究竟为什么会这样,我不确定,但如果你在交互式 Python 中运行 ('a' and ':') 语句,你会看到它返回 ':'。

您的第二次检查也有同样的错误。

考虑使用

if ':' in tstr and 'a' in tstr:

elif 'p' in tstr and ':' in tstr:

不幸的是 Python 只能这么像英语:)

【讨论】:

【参考方案3】:

您的主要问题是您的代码检查子字符串包含不正确:您使用 in 不正确。当你写

if ('a' and ':') in tstr:

它首先评估('a' and ':') 以获得:,然后检查if ':' in tstr。这就是为什么第一个if 块不断评估为真。这是因为and 是一个布尔运算,而x and y 等价于x if bool(x) else y。这个表达式在你到达in 检查之前就被评估了。

你可以用

替换那个代码
if ('a' in tstr) and (':' in tstr)

(对其他检查做类似的操作)

【讨论】:

【参考方案4】:

您可以使用all 概括此测试是否存在多个元素:

if all(ch in tstr for ch in 'a:'):
    etc...

【讨论】:

以上是关于嵌套的 If/Else 控制流在不应该执行时被执行 - 可能是逻辑操作错误的主要内容,如果未能解决你的问题,请参考以下文章

第3弹;流程控制

下面这个if else语句应该理解为几层嵌套?

JS3流程控制

第二节 java流程控制(判断结构+选择结构)

PHP控制语句之“if...else”语句

如何优化这段if else多层嵌套?