Python随机文本生成脚本问题:8字母单词未被选取+性能优化求助
Python随机文本生成脚本问题:8字母单词未被选取+性能优化求助
嗨,我来帮你搞定这两个问题——8字母单词没被选中的bug,还有代码性能提升的优化点,咱们一步一步来:
一、8字母单词未被选取的原因及修复
你的代码里读取单词时犯了一个很容易踩的小坑:从文件里读的每行文本会包含换行符(\n),比如一个8字母的单词,读进来的line实际是"abcdefgh\n",长度是9,而你用len(line) ==8去判断,自然匹配不到,导致eights列表是空的,根本没内容可选!
另外看你的代码最后,choices = [eights]——如果你的需求是要从所有长度的单词里随机选,那这里应该把所有处理后的列表都加进去,比如choices = [fours, fivesLess, sixesLess, sevensLess, eightsLess],不然只会从8字母单词里选(但之前因为长度判断错误,这个列表是空的,所以相当于没选到)。
修复后的单词读取部分代码:
import random # 初始化各长度单词列表 word_lists = { 4: [], 5: [], 6: [], 7: [], 8: [] } # 读取单词列表,先去除换行再判断长度 with open('wordlist.txt') as wordlist: for line in wordlist: word = line.strip() # 先去掉换行符和前后空格 if not word: # 跳过空行 continue word_len = len(word) if word_len in word_lists: word_lists[word_len].append(word) # 把字典里的列表取出来,方便后续使用 fours = word_lists[4] fives = word_lists[5] sixes = word_lists[6] sevens = word_lists[7] eights = word_lists[8]
二、代码性能优化
你的原代码里用while循环+in判断来生成去重的列表,这种方式在单词量较大时速度会非常慢(因为in操作要遍历整个列表),还有频繁打开文件的问题,咱们来优化这些点:
1. 用random.sample替代低效的去重循环
random.sample可以直接从列表里抽取指定数量的不重复随机元素,比你原来的循环高效太多!比如原来生成fivesLess的代码可以改成一行:
# 生成与fours长度相同的不重复随机样本,前提是fives的数量 >= len(fours) # 如果fives数量不够,你可以考虑允许重复,用[random.choice(fives) for _ in range(len(fours))] fivesLess = random.sample(fives, len(fours)) if len(fives) >= len(fours) else [random.choice(fives) for _ in range(len(fours))] sixesLess = random.sample(sixes, len(fours)) if len(sixes) >= len(fours) else [random.choice(sixes) for _ in range(len(fours))] sevensLess = random.sample(sevens, len(fours)) if len(sevens) >= len(fours) else [random.choice(sevens) for _ in range(len(fours))] eightsLess = random.sample(eights, len(fours)) if len(eights) >= len(fours) else [random.choice(eights) for _ in range(len(fours))]
2. 优化文件写入操作
原代码每次生成一行就打开一次文件,频繁的IO操作会拖慢速度,咱们把文件打开放在循环外面,一直保持写入状态:
3. 修复无限循环的逻辑
你的原代码里seedCounter +=0等于没变化,会一直卡在循环里,如果你需要无限生成内容,直接用while True:就好,也可以加个终止条件(比如按Ctrl+C停止)。
优化后的完整代码
import random # 初始化各长度单词列表 word_lists = { 4: [], 5: [], 6: [], 7: [], 8: [] } # 读取并分类单词 with open('wordlist.txt') as wordlist: for line in wordlist: word = line.strip() if not word: continue word_len = len(word) if word_len in word_lists: word_lists[word_len].append(word) fours = word_lists[4] fives = word_lists[5] sixes = word_lists[6] sevens = word_lists[7] eights = word_lists[8] # 生成对应长度的样本列表 def generate_sample(source_list, target_length): if len(source_list) >= target_length: return random.sample(source_list, target_length) # 如果源列表长度不够,重复选取(如果不需要重复可以根据需求调整) return [random.choice(source_list) for _ in range(target_length)] target_len = len(fours) fivesLess = generate_sample(fives, target_len) sixesLess = generate_sample(sixes, target_len) sevensLess = generate_sample(sevens, target_len) eightsLess = generate_sample(eights, target_len) # 所有可选的单词列表(根据你的需求调整这里的内容) choices = [fours, fivesLess, sixesLess, sevensLess, eightsLess] # 无限生成结果并写入文件(按Ctrl+C停止) with open("result1.txt", "a") as f: while True: # 随机选12个单词 seed = [random.choice(random.choice(choices)) for _ in range(12)] f.write(' '.join(seed) + '\n') # 可以加个flush()确保内容及时写入文件,不然可能会缓存 f.flush()
额外说明
- 如果你的需求不是从所有长度里选,而是只选某几种,调整
choices列表里的内容就行; - 如果不需要去重(原代码里的
randFive not in fivesLess是去重逻辑),那直接去掉生成xxxLess的步骤,直接用原有的fives、sixes等列表就行,性能会更好; - 无限循环可以根据你的需求改成固定次数,比如
for _ in range(1000):生成1000行。
备注:内容来源于stack exchange,提问作者Prism Ash




