import re from typing import Any from typing import Optional from typing import Text from typing import Tuple from pypinyin import Style from pypinyin.contrib._tone_rule import right_mark_index _re_number = re.compile(r'\d') class NeutralToneWith5Mixin(): """声调使用数字表示的相关拼音风格下的结果使用 5 标识轻声。 使用方法:: from pypinyin import lazy_pinyin, Style from pypinyin.contrib.neutral_tone import NeutralToneWith5Mixin from pypinyin.converter import DefaultConverter from pypinyin.core import Pinyin # 原来的结果中不会标识轻声 print(lazy_pinyin('好了', style=Style.TONE2)) # 输出: ['ha3o', 'le'] class MyConverter(NeutralToneWith5Mixin, DefaultConverter): pass my_pinyin = Pinyin(MyConverter()) pinyin = my_pinyin.pinyin lazy_pinyin = my_pinyin.lazy_pinyin # 新的结果中使用 ``5`` 标识轻声 print(lazy_pinyin('好了', style=Style.TONE2)) # 输出: ['ha3o', 'le5'] print(pinyin('好了', style=Style.TONE2)) # 输出:[['ha3o'], ['le5']] """ NUMBER_TONE = (Style.TONE2, Style.TONE3, Style.FINALS_TONE2, Style.FINALS_TONE3) # type: Tuple[Style] NUMBER_AT_END = (Style.TONE3, Style.FINALS_TONE3) # type: Tuple[Style] def post_convert_style(self, han: Text, orig_pinyin: Text, converted_pinyin: Text, style: Style, strict: bool, **kwargs: Any) -> Optional[Text]: pre_data = super().post_convert_style( han, orig_pinyin, converted_pinyin, style, strict, **kwargs) if style not in self.NUMBER_TONE: return pre_data if pre_data is not None: converted_pinyin = pre_data # 有声调,跳过 if _re_number.search(converted_pinyin): return converted_pinyin if style in self.NUMBER_AT_END: return '{}5'.format(converted_pinyin) # 找到应该在哪个字母上标声调 mark_index = right_mark_index(converted_pinyin) before = converted_pinyin[:mark_index + 1] after = converted_pinyin[mark_index + 1:] return '{}5{}'.format(before, after)