LEEFEI571 发表于 2024-12-8 17:41:44

if…else…嵌套的困惑

我在做小甲鱼老师的课后练习题,如题如下:

0. 请编写一个程序,判断给定的字符串 s 中括号的写法是否合法。

条件:

字符串仅包含 '('、')'、'['、']'、'{'、'}' 这三对括号的组合
•        左右括号必须成对编写,比如 "()" 是合法的,"(" 则是非法的
•        左右括号必须以正确的顺序闭合,比如 "{()}" 是合法的,"{(})" 则是非法的
具体情况请见附件图片示例.

代码答案如下:
s = input("请输入测试字符串:")

# 创建一个特殊列表
stack = []
   
for c in s:
    # 如果是左括号,那么添加到特殊列表中
    if c == '(' or c == '[' or c == '{':
      stack.append(c)
    # 如果是右括号的情况
    else:
      # 如果碰到右括号,但特殊列表中没有左括号,那么肯定是非法的
      if len(stack) == 0:
            print("非法T_T")
            break
   
      # 逐个给出 c 对应的右括号 d
      if c == ')':
            d = '('
      elif c == ']':
            d = '['
      elif c == '}':
            d = '{'
   
      # 对比 d 和从特殊列表尾部弹出的元素
      if d != stack.pop():
            print("非法T_T")
            break
else:
    # 如果循环走完,特殊列表不为空,那么肯定是左括号比右括号多的情况
    # 那肯定有同学会问:右括号比左括号多的情况在哪里判断?
    # 小甲鱼答:在上面 d != stack.pop() 的判断中已经可以排除了~
    if len(stack) == 0:
      print("合法^o^")
    else:
      print("非法T_T")

我参照答案试了一下,但发现如果把if d != stack.pop():语句中的if改为elif,则得出完全相反的答案.
当if d != stack.pop():时,如果我输入[],程序输出”合法T_T”,请见if截图.
当改为elif d != stack.pop():时,如果我输入[],程序则输出”非法T_T”,请见elif截图.
我的困惑是为什么d != stack.pop():语句前缀为if或elif时,得出的结论完全相反?请大佬帮忙指点迷津一下,谢谢!


jackz007 发表于 2024-12-8 19:26:11

本帖最后由 jackz007 于 2024-12-8 19:43 编辑

【代码1】:
      if c == ')':
            d = '('
      elif c == ']':
            d = '['
      elif c == '}':
            d = '{'
   
      # 对比 d 和从特殊列表尾部弹出的元素
      if d != stack.pop():
            print("非法T_T")
            break
【代码2】:
      if c == ')':
            d = '('
      elif c == ']':
            d = '['
      elif c == '}':
            d = '{'
      elif d != stack.pop():
            print("非法T_T")
            break
      【代码1】是两条相互独立的 if 语句,第一条 if 语句根据变量 c 的值,为变量 d 赋予对应的值,第二条 if 语句判断当前字符与 stack[] 的最后那个字符是否相同,并从 stack[] 中删除这个元素;如果把第二条 if 语句的 if 改为 elif,则原本的两条 if 语句被合并为一条,这就是【代码2】的情形,新改为 elif 的语句和前面的 if ... elif 为接续关系,只有在变量 c 的值不是 ')'、']'、'}' 的时候才会有机会被执行,在本题所设定的条件下,新改为 elif 的语句永远都没有机会被执行,这就导致一个问题,在循环结束的时候,stack[] 必定不会为空,而 stack[] 为空是判断括号匹配的重要标志,这就是本例修改后不能正确判定的原因。
      【代码2】还有一个致命的缺陷,if ... elif ... else 所判定的条件应该是由同一个或多个变量构成的表达式,这些表达式在逻辑上互不重叠,彼此之间应该是互补关系,就是说,在同一个 if ... elif ... else 系统中,判断条件必须统一,既然使用变量 c 作为判断依据,就不可以随意变更为 d。

jackz007 发表于 2024-12-8 20:00:53

         本题合理使用字典可以大幅度简化代码:
e , stack , f = {'}' : '{' , ']' : '[',')' : '('} , [] , False
s = input("请输入测试字符串:")
for c in s :
    if c in e . values() :
      stack . append(c)
    else :
      if not stack or e != stack . pop() :
            break
else :
    if not stack :
      f = True
print("合法^o^") if f else print("非法T_T")
      运行实况:
D:\\Python>python x.py
请输入测试字符串:(((([[[[{{{{}}}}(())]]]]}}}}
非法T_T

D:\\Python>python x.py
请输入测试字符串:(((([[[[{{{{}}}}(())]]]]))))
合法^o^

D:\\Python>

LEEFEI571 发表于 2024-12-8 20:18:15

jackz007 发表于 2024-12-8 20:00
本题合理使用字典可以大幅度简化代码:

      运行实况:

大神,请受我一拜

LEEFEI571 发表于 2024-12-8 20:32:46

jackz007 发表于 2024-12-8 19:26
【代码1】:
      if c == ')':
            d = '('


Jack兄:
   麻烦问下你在讲解【代码1】的时候说到” 第二条 if 语句判断当前字符与 stack[] 的最后那个字符是否相同,并从 stack[] 中删除这个元素”,这个没问题,但是你后面说的” 这就导致一个问题,在循环结束的时候,stack[] 必定不会为空,而 stack[] 为空是判断括号匹配的重要标志,这就是本例修改后不能正确判定的原因。”,这块我就不明白了,这里跟stack[]为不为空有什么关系,不是判断当前字符与 stack[] 的最后那个字符是否相同吗?
另外,你编写的代码中if not stack代表什么意思?

新手小白上路,烦请多多指点.

jackz007 发表于 2024-12-8 22:13:49

本帖最后由 jackz007 于 2024-12-8 22:21 编辑

LEEFEI571 发表于 2024-12-8 20:32
Jack兄:
   麻烦问下你在讲解【代码1】的时候说到” 第二条 if 语句判断当前字符与 stack[] 的最后那 ...

      stack[] 为什么得是空的才匹配?
      考虑一下,当输入 s 为 : '((()))' 时,完成循环后,stack[] 的内容是什么?那么,当 s 为:'((()'或 '()))' 的时候呢?
      not stack 是什么意思?
      如果 stack 不为空,那么,stack 对应的逻辑值为 True;如果 stack 为空,则 stack 对应的逻辑值为 False,not stack 对应的逻辑值为 True,翻译成文字的话:
if not stack :
      这一句的意思是,如果 stack 是空列表。

LEEFEI571 发表于 7 天前

jackz007 发表于 2024-12-8 22:13
stack[] 为什么得是空的才匹配?
      考虑一下,当输入 s 为 : '((()))' 时,完成循环后,sta ...

Jack兄,

问一下为什么stack作为列表可以用于if语句进行判断, 如stack为空列表就不去执行if语句块内容,stack为非空列表则去执行if语句块内容. 但是我要是用stack == True 或 stack == False 进行真值比较时,则均为False, 那如果均为False的情况, if语句又为什么能够进行True/False的判断呢? 麻烦指点一下,谢谢!

jackz007 发表于 7 天前

本帖最后由 jackz007 于 2024-12-14 16:29 编辑

LEEFEI571 发表于 2024-12-14 15:29
Jack兄,

问一下为什么stack作为列表可以用于if语句进行判断, 如stack为空列表就不去执行if语句块内容, ...

      表达式
if not stack
      使用的是 stack 的逻辑值,而不是 stack 的值本身,在 Python 里,一个变量的值和逻辑值完全是两回事,不可以用 stack == False 来判定列表 stack 是否为空。举个例子,执行 n = 5,n 就是一个整型数,n 的值可以有无数个,但是,它的逻辑值一定只可能有两个,当 n = 0 时,其逻辑值为 False,当 n != 0 时,其逻辑值为 True,当然,n = 5,其逻辑值就是 True 了。

LEEFEI571 发表于 7 天前

jackz007 发表于 2024-12-14 16:19
表达式

      使用的是 stack 的逻辑值,而不是 stack 的值本身,在 Python 里,一个变 ...

清楚了,感谢Jack兄不吝赐教!
页: [1]
查看完整版本: if…else…嵌套的困惑