[编程心得]用Python给汉字加上带音调的拼音

作为一个南方人,拼音没学好那似乎已是一件非常正常的事。什么卷舌音、鼻音,也只有在近几年才算是分清了一部分。但尴尬的事情仍在继续,发短信的时候,总有些字拼得不准;说话的时候,总有些字没有卷舌、或忘了加鼻音……痛定思痛,于是有了一个用SuperMemo来强化拼音的训练方案。

要实现这个方案,得具备两个条件,一是选定汉字范围——舍得选的是一级国标汉字,共计3700余个;二是利用程序将这些汉字转化为拼音,要求拼音带上音调,这个就需要对转换精灵进行适度的改造。

舍得以HzqGhost(小强)童鞋的代码为蓝本,进行了如下的改造:

  1. 编码部分采用这份码表:下载地址
  2. 源代码为python2.x的,改造为python 3.x;
  3. 在给韵母添加声调的部分代码,原代码有个别地方出现错误,在我家傻妹的提醒下,舍得修复了这一错误;

下面是相关的部分代码,分段描述:

1、读入码表文件,转成dict:

        fileName = './Mandarin.dat'
        self.dict = {}
        for line in open(fileName):
            k, v = line.split('\t')
            self.dict[k] = v

2、然后对传入的中文字符串进行处理:

        self.yunmu = ( 'ang','eng','ing','ong','an','en','in','un','ai','ei','ao','ou','iu','er','en','a','o','e','i','u', 'v')
        self.sheng = {'a':'ā á ǎ à','o':'ō ó ǒ ò','e':'ē é ě è','i':'ī í ǐ ì','u':'ū ú ǔ ù', 'v':'ǖ ǘ ǚ ǜ'}
        result = []
        for char in chars:#chars为传入的中文字符串
            key = "%X" % ord(char)#将汉字转为utf16编码,“码表”文件中用的是这个编码
            try:
                py = self.dict[key].split(" ")[0].strip().lower()#只取查到的拼音第一个值(当有多音字的时候),同时将结果转为小写
                for ym in self.yunmu:
                    if re.search(ym, py):#匹配
                        py = getPy(py, ym)
                        break#只取第一个结果
                result.append(py)
            except:
                result.append(char)
        return " ".join(result)


原来的self.yunmu设置不合理,在碰到'ui','iu','ie','ue'四个韵母时,音调会标在第一个字母上,舍得在元组中去除了'ui','ie','ue'这三个值,这样在匹配时根据a,o,e,i,u的顺序,这三个韵母的音调才会落在第二个字母上。而对于'iu'这个韵母,则需在下面的getPy里作一个特殊的处理:

3、给匹配到的韵母标上音调:

        def getPy(py, ym):
            t = py[-1:].encode('ascii','ignore')#‘码表’中返回的拼音字符串最后一位是数字,表示音调值
            t2 = "%d" % ord(t)
            t3 = (int(t2) - 48)%4 -1
            py2 = py[:-len(ym)-1]#声母
            if ym == "iu":#如果韵母是iu
                letter = self.sheng[ym[1]].split(' ')[t3]#音调字母要标在u上
                ym = ym[0] + letter
            else:                
                letter = self.sheng[ym[0]].split(' ')[t3]#其它情况,音调标在第一个字母上
                ym = letter + ym[1:]
            py = py2 + ym
            return py


最终完整的代码如下:

    def cnCode(self, chars):
        def getPy(py, ym):
            t = py[-1:].encode('ascii','ignore')#‘码表’中返回的拼音字符串最后一位是数字,表示音调值
            t2 = "%d" % ord(t)
            t3 = (int(t2) - 48)%4 -1
            py2 = py[:-len(ym)-1]#声母
            if ym == "iu":#如果韵母是iu
                letter = self.sheng[ym[1]].split(' ')[t3]#音调字母要标在u上
                ym = ym[0] + letter
            else:                
                letter = self.sheng[ym[0]].split(' ')[t3]#其它情况,音调标在第一个字母上
                ym = letter + ym[1:]
            py = py2 + ym
            return py
            
        fileName = './Mandarin.dat'
        self.dict = {}
        for line in open(fileName):
            k, v = line.split('\t')
            self.dict[k] = v

        self.yunmu = ( 'ang','eng','ing','ong','an','en','in','un','ai','ei','ao','ou','iu','er','en','a','o','e','i','u', 'v')
        self.sheng = {'a':'ā á ǎ à','o':'ō ó ǒ ò','e':'ē é ě è','i':'ī í ǐ ì','u':'ū ú ǔ ù', 'v':'ǖ ǘ ǚ ǜ'}
        result = []
        for char in chars:#chars为传入的中文字符串
            key = "%X" % ord(char)#将汉字转为utf16编码,“码表”文件中用的是这个编码
            try:
                py = self.dict[key].split(" ")[0].strip().lower()#只取查到的拼音第一个值(当有多音字的时候),同时将结果转为小写
                for ym in self.yunmu:
                    if re.search(ym, py):#匹配
                        py = getPy(py, ym)
                        break#只取第一个结果
                result.append(py)
            except:
                result.append(char)
        return " ".join(result)

调用的时候,只要这样就可以了:

        chars = "舍得英语魔法学苑"
        print(self.cnCode(chars))

返回的结果如下图所示:

拼音
不过舍得通常会读取当前文本,然后按换行符分割,再逐个传入,得到拼音,最后拼成TAB文本,这样就可以利用转换精灵制作成课程了。这里边的细节就不再一一叙述了。

附上最终完成的课程:

国标汉字拼音课程

本文版权归舍得英语魔法学苑所有,欢迎转载,转载请注明作者和出处。谢谢!
作者:
舍得
首发:
舍得@学习力博客

原文地址:https://www.cnblogs.com/emagic/p/2455132.html