Python单词过滤程序数轮运行后无报错终止问题排查
问题描述
我是Python新手,尝试编写了一款按字母筛选单词列表的简单程序:运行逻辑为用户输入单个字母,告知程序该字母是否存在于待查找目标单词中,程序会逐步过滤缩小词表范围。但实际运行时,在用户输入4个字母后程序就会停止响应,全程未抛出任何错误信息,不再执行预设功能。
问题复现代码
f = open("worte.txt", "r") words = f.read().split() f.close() print("list contains %i words" % len(words)) words = [word.upper() for word in words] lengthword = int(input("How long is the word?")) correctlength = [] correctletter = [] for i in words: if len(i) == lengthword: correctlength.append(i) print("list contains %i words" % len(correctlength)) while True: userinput = input("Enter a letter").upper() inputcorrect = input("Is this letter correct? (Y/N)").upper() if inputcorrect == "Y": for word in correctlength: for letter in word: if userinput == letter: correctletter.append(word) break correctlength = correctletter correctletter = [] print(len(correctlength)) print(correctlength) elif inputcorrect == "N": for word in correctlength: for letter in word: if userinput not in letter: correctletter.append(word) continue else: break correctlength = correctletter print(len(correctlength)) print(correctlength)
故障原因
程序不是真的卡死崩溃,是筛选逻辑存在bug,导致待遍历的单词列表几轮循环后长度爆炸式增长,遍历耗时太长看起来像停止响应,全程不会抛出错误。核心问题有3个:
- 输入N(标记字母不在目标单词中)的筛选逻辑错误:逐字符遍历单词时,只要碰到第一个不等于排除字母的字符,就直接把整个单词加入结果列表,完全不检查单词剩余位置是否包含要排除的字母,筛选完全失效
- 单词重复追加:只要单词里有k个字符不等于排除字母,这个单词就会被重复追加k次。比如5个字母的单词不含排除字母,就会被重复加5次,每轮循环列表长度都会翻数倍
- N分支执行完后没有清空临时列表
correctletter,下一轮循环会继续往存有旧数据的列表里追加内容,进一步加快列表膨胀速度。通常跑3-4轮后列表长度就会达到几十万甚至上百万,遍历耗时极长,看起来就像停止响应。
修复后代码
直接用Python内置的成员判断in实现筛选逻辑,去掉容易出错的嵌套逐字符循环,同时修正临时列表清空的问题:
# 用with管理文件读写,避免手动关文件的疏漏,建议指定编码防止乱码 with open("worte.txt", "r", encoding="utf-8") as f: words = [word.upper() for word in f.read().split()] print("list contains %i words" % len(words)) lengthword = int(input("How long is the word?")) # 按单词长度做初筛 correctlength = [word for word in words if len(word) == lengthword] print("list contains %i words" % len(correctlength)) while True: userinput = input("Enter a letter").upper() inputcorrect = input("Is this letter correct? (Y/N)").upper() # 每轮循环先初始化空的临时结果列表,避免旧数据残留 correctletter = [] if inputcorrect == "Y": # 保留包含当前输入字母的单词 for word in correctlength: if userinput in word: correctletter.append(word) elif inputcorrect == "N": # 排除包含当前输入字母的单词 for word in correctlength: if userinput not in word: correctletter.append(word) correctlength = correctletter print(f"当前匹配单词数量:{len(correctlength)}") print(correctlength)
修复点说明:
- 从根源解决临时列表脏数据残留的问题,每轮循环开始时先初始化空的结果列表
- 用
in/not in直接判断字母和单词的包含关系,去掉冗余的嵌套循环,同时解决单词重复添加、筛选逻辑错误的问题 - 把两个分支重复的赋值、打印逻辑抽离,减少冗余代码
内容的提问来源于stack exchange,提问作者Thore Wagner
相关产品推荐
相关产品推荐

