jieba源碼研讀筆記(十四) - 詞性標注函數入口

jieba源碼研讀筆記(十四) - 詞性標注函數入口

前言

在前面兩篇中介紹了__cut_DAG_NO_HMM__cut_DAG函數。

本篇介紹的__cut_internal函數是__cut_DAG__cut_DAG_NO_HMM這兩個函數的入口,它的參數HMM可以選擇要使用哪一個。

本篇還會介紹_lcut_internal_lcut_internal_no_hmmcutlcut,它們是__cut_internal的wrapper,讓它變得更易用。

__cut_internal函數

以下代碼中用到的正則表達式,包括:re_han_internalre_skip_internalre_numre_eng已於jieba源碼研讀筆記(四) - 正則表達式中介紹。

在以下代碼中,先依HMM這個參數來決定要使用__cut_DAG__cut_DAG_NO_HMM,然後改以cut_blk來稱呼它。

一開始用re_han_internal來將句子分割成可處理的及不可處理的部份。可處理的部份直接呼叫cut_blk,不可處理的部份則利用正則表達式匹配的方式來做詞性標注。

class POSTokenizer(object):
    # ...
    def __cut_internal(self, sentence, HMM=True):
        self.makesure_userdict_loaded()
        sentence = strdecode(sentence)
        #re_han_internal:一個或多個中文或英數字或+#&._
        #能與re_han_internal匹配代表可以被__cut_DAG或__cut_DAG_NO_HMM處理
        blocks = re_han_internal.split(sentence)
        #決定要使用__cut_DAG或__cut_DAG_NO_HMM中的一個
        if HMM:
            cut_blk = self.__cut_DAG
        else:
            cut_blk = self.__cut_DAG_NO_HMM

        for blk in blocks:
            #如果與re_han_internal相匹配,代表可被__cut_DAG及__cut_DAG_NO_HMM所處理
            if re_han_internal.match(blk):
                for word in cut_blk(blk):
                    yield word
            else:
                #無法與re_han_internal匹配的blk
                #re_skip_internal:換行字元及空白字元
                tmp = re_skip_internal.split(blk)
                for x in tmp:
                    if re_skip_internal.match(x):
                        #換行字元及空白字元的詞性為'x'(未知)
                        yield pair(x, 'x')
                    else:
                        #非空白字元,檢查它是否為數字或英文
                        for xx in x:
                            if re_num.match(xx):
                                yield pair(xx, 'm')
                            elif re_eng.match(x):
                                yield pair(xx, 'eng')
                            else:
                                yield pair(xx, 'x')

__cut_internal的wrapper

POSTokenizercut函數是__cut_internal函數的wrapper,接受的參數與__cut_internal一樣是sentenceHMM。它會依據HMM來決定要調用__cut_DAG_NO_HMM__cut_DAG中的一個。

_lcut_internal_lcut_internal_no_hmmlcut分別是__cut_internal(sentence)__cut_internal(sentence, False)cut三個函數的wrapper,將它們的輸出由generator型別轉為list型別。

class POSTokenizer(object):
    # ...
    def cut(self, sentence, HMM=True):
        for w in self.__cut_internal(sentence, HMM=HMM):
            yield w
            
    def _lcut_internal(self, sentence):
        return list(self.__cut_internal(sentence))

    def _lcut_internal_no_hmm(self, sentence):
        return list(self.__cut_internal(sentence, False))

    def lcut(self, *args, **kwargs):
        return list(self.cut(*args, **kwargs))

參考連結

jieba源碼研讀筆記(四) - 正則表達式

上一篇:TASK2笔记+代码


下一篇:文本特征抽取及jieba处理中文问题