neutral_tone.py 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. # -*- coding: utf-8 -*-
  2. from __future__ import unicode_literals
  3. import re
  4. from pypinyin import Style
  5. from pypinyin.contrib._tone_rule import right_mark_index
  6. _re_number = re.compile(r'\d')
  7. class NeutralToneWith5Mixin(object):
  8. """声调使用数字表示的相关拼音风格下的结果使用 5 标识轻声。
  9. 使用方法::
  10. from pypinyin import lazy_pinyin, Style
  11. from pypinyin.contrib.neutral_tone import NeutralToneWith5Mixin
  12. from pypinyin.converter import DefaultConverter
  13. from pypinyin.core import Pinyin
  14. # 原来的结果中不会标识轻声
  15. print(lazy_pinyin('好了', style=Style.TONE2))
  16. # 输出: ['ha3o', 'le']
  17. class MyConverter(NeutralToneWith5Mixin, DefaultConverter):
  18. pass
  19. my_pinyin = Pinyin(MyConverter())
  20. pinyin = my_pinyin.pinyin
  21. lazy_pinyin = my_pinyin.lazy_pinyin
  22. # 新的结果中使用 ``5`` 标识轻声
  23. print(lazy_pinyin('好了', style=Style.TONE2))
  24. # 输出: ['ha3o', 'le5']
  25. print(pinyin('好了', style=Style.TONE2))
  26. # 输出:[['ha3o'], ['le5']]
  27. """
  28. NUMBER_TONE = (Style.TONE2, Style.TONE3, Style.FINALS_TONE2,
  29. Style.FINALS_TONE3)
  30. NUMBER_AT_END = (Style.TONE3, Style.FINALS_TONE3)
  31. def post_convert_style(self, han, orig_pinyin, converted_pinyin,
  32. style, strict, **kwargs):
  33. pre_data = super(NeutralToneWith5Mixin, self).post_convert_style(
  34. han, orig_pinyin, converted_pinyin, style, strict, **kwargs)
  35. if style not in self.NUMBER_TONE:
  36. return pre_data
  37. if pre_data is not None:
  38. converted_pinyin = pre_data
  39. if not converted_pinyin: # 空字符串
  40. return converted_pinyin
  41. # 有声调,跳过
  42. if _re_number.search(converted_pinyin):
  43. return converted_pinyin
  44. if style in self.NUMBER_AT_END:
  45. return '{}5'.format(converted_pinyin)
  46. # 找到应该在哪个字母上标声调
  47. mark_index = right_mark_index(converted_pinyin)
  48. before = converted_pinyin[:mark_index + 1]
  49. after = converted_pinyin[mark_index + 1:]
  50. return '{}5{}'.format(before, after)