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: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。 本题合理使用字典可以大幅度简化代码:
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> jackz007 发表于 2024-12-8 20:00
本题合理使用字典可以大幅度简化代码:
运行实况:
大神,请受我一拜 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: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 是空列表。 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 于 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 了。 jackz007 发表于 2024-12-14 16:19
表达式
使用的是 stack 的逻辑值,而不是 stack 的值本身,在 Python 里,一个变 ...
清楚了,感谢Jack兄不吝赐教!
页:
[1]