简介:

这个代码是看了Peter大神的文章自己模仿这写的,基本就是copy人家的思路,不过自己在代码之间添加了一些注释。

自己写这个的目的是练习自己写Python代码的能力,而且在这个过程中确实收获还是蛮多的!

代码及其注释

# -*- coding: utf-8 -*-

import re
from collections import Counter

def words(text):
    return re.findall(r'\w+', text.lower())
    # findall函数作用(可查看用户手册)在这里就是用来将txt中的每一个单词进行分离,在返回一个字符串列表
        
WORDS = Counter(words(open('D:\\PythonWorkSpace\\big.txt').read()))
# 这里的WORDS就是一个无序的集合,里面存储的是K-V:K是单词,V是单词在txt中出现的次数。这个是由Count函数使得的

def P(word, N = sum(WORDS.values())):
    return WORDS[word] / N
    # P这个函数是用来计算word这个词在txt样本中出现的概率,当word没有出现过,WORDS[word]会返回0
        
def known(words):
# known这个函数返回一个集合,集合的内容是即在words这个集合中,又在WORDS中的单词
    return set(w for w in words if w in WORDS)
    
def edits1(word):
# edits1函数的作用是返回对word这个单词一次编辑后可能得到的所有结果的集合
    letters = 'abcdefghijklmnopqrstuvwxyz'
    splits = [(word[:i], word[i:]) for i in range(len(word) + 1)]
    # splits 在这里就是由tuple组成的list,每一个tuple是word单词的分解形式
    # 这里面字符串索引得认真去研究一波,比如word[0:0]结果是空字符,word[aN:aN]结果也是很空字符
    deletes = [L + R[1:] for L, R in splits if R]
    # 这里面的R如果是空字符,就判断为False
    # deletes 在这里的作用就是得到word删掉一个字母的所有字符的集合
    transposes = [L + R[1] + R[0] + R[2:] for L, R in splits if len(R) > 1]
    # transposes 在这里的作用就是将word单词中任意两个字母调换一次位置后得到的所有单词的集合
    replaces = [L + c + R[1:] for L, R in splits if R for c in letters]
    # replaces 在这里的用途是将word单词中删掉一个字母后可能得到的单词的集合
    inserts = [L + c + R for L, R in splits for c in letters]
    # inserts 在此处的作用是插入一个字母到word单词中后可能得到的单词的集合
    return set(deletes + transposes + replaces + inserts)
        
def edits2(word):
# edits2函数的作用是返回对word这个单词进行两次编辑后可能得到的所有结果的集合
    return (e2 for e1 in edits1(word) for e2 in edits1(e1))
    
def candidates(word):
# candidates函数返回的内容:如果word在txt中出现过,则就返回word,如果没有的话,就返回对word编辑一次后获得的字符集中在txt中出现过的字符构成的集合,如果还是没有的话就返回二次编辑的,如果二次编辑的也没有的话,就返回word
# 看了写这个代码的人的解释,这个函数算是一个错误模型,用来保证所获得的结果是比较可信的
    return (known([word]) or known(edits1(word)) or known(edits2(word)) or [word])
    
def correction(word):
    return max(candidates(word), key = P)

下面一个代码是测试用的:

import sys
sys.path.append('D:\\PythonWorkSpace\\SpellingCheck.py')

import time
import SpellingCheck

def spelltest(tests, verbose = True):
    start = time.clock()
    good, unknown = 0, 0
    n = len(tests)
    for right, wrong in tests:
        w = SpellingCheck.correction(wrong)
        good += (w == right)
        if w != right:
            unknown += (right not in SpellingCheck.WORDS)
            if verbose:
                print('correction( {} ) => {} ( {} ); except {} ( {} )'.format(wrong, w, SpellingCheck.WORDS[w], right, SpellingCheck.WORDS[right]))
                
    dt = time.clock() - start
    
    print('{:.0%} of {} correct ({:.0%} unknown) at {:.0f} words per second'.format(good / n, n, unknown / n, n / dt))
    
def Testset(lines):
    return [(right, wrong) for (right, wrongs) in (line.split(':') for line in lines) for wrong in wrongs.split()]
    
spelltest(Testset(open('D:\\PythonWorkSpace\\spell-testset.txt')))
说明

我将代码中测试的big.txt和spell-testset.txt放在D:\\PythonWorkSpace目录面

  • big.txt文件下载地址:http://norvig.com/big.txt
  • spell-testset.txt文件下载地址:http://norvig.com/spell-testset1.txt

总结

只能说自己的Python基础还是比较薄弱的,得加强!