_tone_convert.py 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577
  1. # -*- coding: utf-8 -*-
  2. from __future__ import unicode_literals
  3. import re
  4. from pypinyin import phonetic_symbol
  5. from pypinyin.style._tone_rule import right_mark_index
  6. from pypinyin.style._constants import RE_TONE3, RE_TONE2
  7. from pypinyin.style.tone import converter
  8. from pypinyin.style._utils import (
  9. get_initials, replace_symbol_to_no_symbol,
  10. get_finals, replace_symbol_to_number
  11. )
  12. _re_number = re.compile(r'\d')
  13. def to_normal(pinyin, v_to_u=False):
  14. """将 :py:attr:`~pypinyin.Style.TONE`、
  15. :py:attr:`~pypinyin.Style.TONE2` 或
  16. :py:attr:`~pypinyin.Style.TONE3` 风格的拼音转换为
  17. :py:attr:`~pypinyin.Style.NORMAL` 风格的拼音
  18. :param pinyin: :py:attr:`~pypinyin.Style.TONE`、
  19. :py:attr:`~pypinyin.Style.TONE2` 或
  20. :py:attr:`~pypinyin.Style.TONE3` 风格的拼音
  21. :param v_to_u: 是否使用 ``ü`` 代替原来的 ``v``,
  22. 当为 False 时结果中将使用 ``v`` 表示 ``ü``
  23. :return: :py:attr:`~pypinyin.Style.NORMAL` 风格的拼音
  24. Usage::
  25. >>> from pypinyin.contrib.tone_convert import to_normal
  26. >>> to_normal('zhōng')
  27. 'zhong'
  28. >>> to_normal('zho1ng')
  29. 'zhong'
  30. >>> to_normal('zhong1')
  31. 'zhong'
  32. >>> to_normal('lüè')
  33. 'lve'
  34. >>> to_normal('lüè', v_to_u=True)
  35. 'lüe'
  36. """
  37. s = tone_to_tone2(pinyin, v_to_u=True)
  38. s = tone2_to_normal(s)
  39. return _fix_v_u(pinyin, s, v_to_u=v_to_u)
  40. def to_tone(pinyin):
  41. """将 :py:attr:`~pypinyin.Style.TONE2` 或
  42. :py:attr:`~pypinyin.Style.TONE3` 风格的拼音转换为
  43. :py:attr:`~pypinyin.Style.TONE` 风格的拼音
  44. :param pinyin: :py:attr:`~pypinyin.Style.TONE2` 或
  45. :py:attr:`~pypinyin.Style.TONE3` 风格的拼音
  46. :return: :py:attr:`~pypinyin.Style.TONE` 风格的拼音
  47. Usage::
  48. >>> from pypinyin.contrib.tone_convert import to_tone
  49. >>> to_tone('zho1ng')
  50. 'zhōng'
  51. >>> to_tone('zhong1')
  52. 'zhōng'
  53. """
  54. pinyin = pinyin.replace('v', 'ü')
  55. if not _re_number.search(pinyin):
  56. return pinyin
  57. s = tone_to_tone2(pinyin)
  58. s = tone2_to_tone(s)
  59. return s
  60. def to_tone2(pinyin, v_to_u=False, neutral_tone_with_five=False, **kwargs):
  61. """将 :py:attr:`~pypinyin.Style.TONE` 或
  62. :py:attr:`~pypinyin.Style.TONE3` 风格的拼音转换为
  63. :py:attr:`~pypinyin.Style.TONE2` 风格的拼音
  64. :param pinyin: :py:attr:`~pypinyin.Style.TONE` 或
  65. :py:attr:`~pypinyin.Style.TONE3` 风格的拼音
  66. :param v_to_u: 是否使用 ``ü`` 代替原来的 ``v``,
  67. 当为 False 时结果中将使用 ``v`` 表示 ``ü``
  68. :param neutral_tone_with_five: 是否使用 ``5`` 标识轻声
  69. :param kwargs: 用于兼容老版本的 ``neutral_tone_with_5`` 参数,当传入
  70. ``neutral_tone_with_5`` 参数时,
  71. 将覆盖 ``neutral_tone_with_five`` 的值。
  72. :return: :py:attr:`~pypinyin.Style.TONE2` 风格的拼音
  73. Usage::
  74. >>> from pypinyin.contrib.tone_convert import to_tone2
  75. >>> to_tone2('zhōng')
  76. 'zho1ng'
  77. >>> to_tone2('zhong1')
  78. 'zho1ng'
  79. >>> to_tone2('shang')
  80. 'shang'
  81. >>> to_tone2('shang', neutral_tone_with_five=True)
  82. 'sha5ng'
  83. >>> to_tone2('lüè')
  84. 'lve4'
  85. >>> to_tone2('lüè', v_to_u=True)
  86. 'lüe4'
  87. """
  88. if kwargs.get('neutral_tone_with_5', None) is not None:
  89. neutral_tone_with_five = kwargs['neutral_tone_with_5']
  90. pinyin = pinyin.replace('5', '')
  91. s = tone_to_tone3(
  92. pinyin, v_to_u=True, neutral_tone_with_five=neutral_tone_with_five)
  93. s = tone3_to_tone2(s)
  94. return _fix_v_u(pinyin, s, v_to_u)
  95. def to_tone3(pinyin, v_to_u=False, neutral_tone_with_five=False, **kwargs):
  96. """将 :py:attr:`~pypinyin.Style.TONE` 或
  97. :py:attr:`~pypinyin.Style.TONE2` 风格的拼音转换为
  98. :py:attr:`~pypinyin.Style.TONE3` 风格的拼音
  99. :param pinyin: :py:attr:`~pypinyin.Style.TONE` 或
  100. :py:attr:`~pypinyin.Style.TONE2` 风格的拼音
  101. :param v_to_u: 是否使用 ``ü`` 代替原来的 ``v``,
  102. 当为 False 时结果中将使用 ``v`` 表示 ``ü``
  103. :param neutral_tone_with_five: 是否使用 ``5`` 标识轻声
  104. :param kwargs: 用于兼容老版本的 ``neutral_tone_with_5`` 参数,当传入
  105. ``neutral_tone_with_5`` 参数时,
  106. 将覆盖 ``neutral_tone_with_five`` 的值。
  107. :return: :py:attr:`~pypinyin.Style.TONE2` 风格的拼音
  108. Usage::
  109. >>> from pypinyin.contrib.tone_convert import to_tone3
  110. >>> to_tone3('zhōng')
  111. 'zhong1'
  112. >>> to_tone3('zho1ng')
  113. 'zhong1'
  114. >>> to_tone3('shang')
  115. 'shang'
  116. >>> to_tone3('shang', neutral_tone_with_five=True)
  117. 'shang5'
  118. >>> to_tone3('lüè')
  119. 'lve4'
  120. >>> to_tone3('lüè', v_to_u=True)
  121. 'lüe4'
  122. """
  123. if kwargs.get('neutral_tone_with_5', None) is not None:
  124. neutral_tone_with_five = kwargs['neutral_tone_with_5']
  125. pinyin = pinyin.replace('5', '')
  126. s = tone_to_tone2(
  127. pinyin, v_to_u=True, neutral_tone_with_five=neutral_tone_with_five)
  128. s = tone2_to_tone3(s)
  129. return _fix_v_u(pinyin, s, v_to_u)
  130. def to_initials(pinyin, strict=True):
  131. """将 :py:attr:`~pypinyin.Style.TONE`、
  132. :py:attr:`~pypinyin.Style.TONE2` 、
  133. :py:attr:`~pypinyin.Style.TONE3` 或
  134. :py:attr:`~pypinyin.Style.NORMAL` 风格的拼音转换为
  135. :py:attr:`~pypinyin.Style.INITIALS` 风格的拼音
  136. :param pinyin: :py:attr:`~pypinyin.Style.TONE`、
  137. :py:attr:`~pypinyin.Style.TONE2` 、
  138. :py:attr:`~pypinyin.Style.TONE3` 或
  139. :py:attr:`~pypinyin.Style.NORMAL` 风格的拼音
  140. :param strict: 返回结果是否严格遵照《汉语拼音方案》来处理声母和韵母,
  141. 详见 :ref:`strict`
  142. :return: :py:attr:`~pypinyin.Style.INITIALS` 风格的拼音
  143. Usage::
  144. >>> from pypinyin.contrib.tone_convert import to_initials
  145. >>> to_initials('zhōng')
  146. 'zh'
  147. """
  148. return get_initials(pinyin, strict=strict)
  149. def to_finals(pinyin, strict=True, v_to_u=False):
  150. """将 :py:attr:`~pypinyin.Style.TONE`、
  151. :py:attr:`~pypinyin.Style.TONE2` 、
  152. :py:attr:`~pypinyin.Style.TONE3` 或
  153. :py:attr:`~pypinyin.Style.NORMAL` 风格的拼音转换为
  154. :py:attr:`~pypinyin.Style.FINALS` 风格的拼音
  155. :param pinyin: :py:attr:`~pypinyin.Style.TONE`、
  156. :py:attr:`~pypinyin.Style.TONE2` 、
  157. :py:attr:`~pypinyin.Style.TONE3` 或
  158. :py:attr:`~pypinyin.Style.NORMAL` 风格的拼音
  159. :param strict: 返回结果是否严格遵照《汉语拼音方案》来处理声母和韵母,
  160. 详见 :ref:`strict`
  161. :param v_to_u: 是否使用 ``ü`` 代替原来的 ``v``,
  162. 当为 False 时结果中将使用 ``v`` 表示 ``ü``
  163. :return: :py:attr:`~pypinyin.Style.FINALS` 风格的拼音
  164. Usage::
  165. >>> from pypinyin.contrib.tone_convert import to_finals
  166. >>> to_finals('zhōng')
  167. 'ong'
  168. """
  169. new_pinyin = replace_symbol_to_no_symbol(pinyin).replace('v', 'ü')
  170. finals = get_finals(new_pinyin, strict=strict)
  171. finals = _fix_v_u(finals, finals, v_to_u)
  172. return finals
  173. def to_finals_tone(pinyin, strict=True):
  174. """将 :py:attr:`~pypinyin.Style.TONE`、
  175. :py:attr:`~pypinyin.Style.TONE2` 或
  176. :py:attr:`~pypinyin.Style.TONE3` 风格的拼音转换为
  177. :py:attr:`~pypinyin.Style.FINALS_TONE` 风格的拼音
  178. :param pinyin: :py:attr:`~pypinyin.Style.TONE`、
  179. :py:attr:`~pypinyin.Style.TONE2` 或
  180. :py:attr:`~pypinyin.Style.TONE3` 风格的拼音
  181. :param strict: 返回结果是否严格遵照《汉语拼音方案》来处理声母和韵母,
  182. 详见 :ref:`strict`
  183. :return: :py:attr:`~pypinyin.Style.FINALS_TONE` 风格的拼音
  184. Usage::
  185. >>> from pypinyin.contrib.tone_convert import to_finals_tone
  186. >>> to_finals_tone('zhōng')
  187. 'ōng'
  188. """
  189. finals = to_finals_tone2(pinyin, strict=strict)
  190. finals = tone2_to_tone(finals)
  191. return finals
  192. def to_finals_tone2(pinyin, strict=True, v_to_u=False,
  193. neutral_tone_with_five=False):
  194. """将 :py:attr:`~pypinyin.Style.TONE`、
  195. :py:attr:`~pypinyin.Style.TONE2` 或
  196. :py:attr:`~pypinyin.Style.TONE3` 风格的拼音转换为
  197. :py:attr:`~pypinyin.Style.FINALS_TONE2` 风格的拼音
  198. :param pinyin: :py:attr:`~pypinyin.Style.TONE`、
  199. :py:attr:`~pypinyin.Style.TONE2` 或
  200. :py:attr:`~pypinyin.Style.TONE3` 风格的拼音
  201. :param strict: 返回结果是否严格遵照《汉语拼音方案》来处理声母和韵母,
  202. 详见 :ref:`strict`
  203. :param v_to_u: 是否使用 ``ü`` 代替原来的 ``v``,
  204. 当为 False 时结果中将使用 ``v`` 表示 ``ü``
  205. :param neutral_tone_with_five: 是否使用 ``5`` 标识轻声
  206. :return: :py:attr:`~pypinyin.Style.FINALS_TONE2` 风格的拼音
  207. Usage::
  208. >>> from pypinyin.contrib.tone_convert import to_finals_tone2
  209. >>> to_finals_tone2('zhōng')
  210. 'o1ng'
  211. """
  212. pinyin = pinyin.replace('5', '')
  213. finals = to_finals_tone3(pinyin, strict=strict, v_to_u=v_to_u,
  214. neutral_tone_with_five=neutral_tone_with_five)
  215. finals = tone3_to_tone2(finals, v_to_u=v_to_u)
  216. return finals
  217. def to_finals_tone3(pinyin, strict=True, v_to_u=False,
  218. neutral_tone_with_five=False):
  219. """将 :py:attr:`~pypinyin.Style.TONE`、
  220. :py:attr:`~pypinyin.Style.TONE2` 或
  221. :py:attr:`~pypinyin.Style.TONE3` 风格的拼音转换为
  222. :py:attr:`~pypinyin.Style.FINALS_TONE3` 风格的拼音
  223. :param pinyin: :py:attr:`~pypinyin.Style.TONE`、
  224. :py:attr:`~pypinyin.Style.TONE2` 或
  225. :py:attr:`~pypinyin.Style.TONE3` 风格的拼音
  226. :param strict: 返回结果是否严格遵照《汉语拼音方案》来处理声母和韵母,
  227. 详见 :ref:`strict`
  228. :param v_to_u: 是否使用 ``ü`` 代替原来的 ``v``,
  229. 当为 False 时结果中将使用 ``v`` 表示 ``ü``
  230. :param neutral_tone_with_five: 是否使用 ``5`` 标识轻声
  231. :return: :py:attr:`~pypinyin.Style.FINALS_TONE3` 风格的拼音
  232. Usage::
  233. >>> from pypinyin.contrib.tone_convert import to_finals_tone3
  234. >>> to_finals_tone3('zhōng')
  235. 'ong1'
  236. """
  237. pinyin = pinyin.replace('5', '')
  238. finals = to_finals(pinyin, strict=strict, v_to_u=v_to_u)
  239. if not finals:
  240. return finals
  241. numbers = _re_number.findall(replace_symbol_to_number(pinyin))
  242. if not numbers:
  243. if neutral_tone_with_five:
  244. numbers = ['5']
  245. else:
  246. return finals
  247. number = numbers[0]
  248. finals = finals + number
  249. return finals
  250. def tone_to_normal(tone, v_to_u=False):
  251. """将 :py:attr:`~pypinyin.Style.TONE` 风格的拼音转换为
  252. :py:attr:`~pypinyin.Style.NORMAL` 风格的拼音
  253. :param tone: :py:attr:`~pypinyin.Style.TONE` 风格的拼音
  254. :param v_to_u: 是否使用 ``ü`` 代替原来的 ``v``,
  255. 当为 False 时结果中将使用 ``v`` 表示 ``ü``
  256. :return: :py:attr:`~pypinyin.Style.NORMAL` 风格的拼音
  257. Usage::
  258. >>> from pypinyin.contrib.tone_convert import tone_to_normal
  259. >>> tone_to_normal('zhōng')
  260. 'zhong'
  261. >>> tone_to_normal('lüè')
  262. 'lve'
  263. >>> tone_to_normal('lüè', v_to_u=True)
  264. 'lüe'
  265. """
  266. s = tone_to_tone2(tone, v_to_u=v_to_u)
  267. s = _re_number.sub('', s)
  268. return _v_to_u(s, v_to_u)
  269. def tone_to_tone2(tone, v_to_u=False, neutral_tone_with_five=False, **kwargs):
  270. """将 :py:attr:`~pypinyin.Style.TONE` 风格的拼音转换为
  271. :py:attr:`~pypinyin.Style.TONE2` 风格的拼音
  272. :param tone: :py:attr:`~pypinyin.Style.TONE` 风格的拼音
  273. :param v_to_u: 是否使用 ``ü`` 代替原来的 ``v``,
  274. 当为 False 时结果中将使用 ``v`` 表示 ``ü``
  275. :param neutral_tone_with_five: 是否使用 ``5`` 标识轻声
  276. :param kwargs: 用于兼容老版本的 ``neutral_tone_with_5`` 参数,当传入
  277. ``neutral_tone_with_5`` 参数时,
  278. 将覆盖 ``neutral_tone_with_five`` 的值。
  279. :return: :py:attr:`~pypinyin.Style.TONE2` 风格的拼音
  280. Usage::
  281. >>> from pypinyin.contrib.tone_convert import tone_to_tone2
  282. >>> tone_to_tone2('zhōng')
  283. 'zho1ng'
  284. >>> tone_to_tone2('shang')
  285. 'shang'
  286. >>> tone_to_tone2('shang', neutral_tone_with_5=True)
  287. 'sha5ng'
  288. >>> tone_to_tone2('lüè')
  289. 'lve4'
  290. >>> tone_to_tone2('lüè', v_to_u=True)
  291. 'lüe4'
  292. """
  293. if kwargs.get('neutral_tone_with_5', None) is not None:
  294. neutral_tone_with_five = kwargs['neutral_tone_with_5']
  295. tone3 = tone_to_tone3(
  296. tone, v_to_u=v_to_u, neutral_tone_with_five=neutral_tone_with_five)
  297. s = tone3_to_tone2(tone3)
  298. return _v_to_u(s, v_to_u)
  299. def tone_to_tone3(tone, v_to_u=False, neutral_tone_with_five=False, **kwargs):
  300. """将 :py:attr:`~pypinyin.Style.TONE` 风格的拼音转换为
  301. :py:attr:`~pypinyin.Style.TONE3` 风格的拼音
  302. :param tone: :py:attr:`~pypinyin.Style.TONE` 风格的拼音
  303. :param v_to_u: 是否使用 ``ü`` 代替原来的 ``v``,
  304. 当为 False 时结果中将使用 ``v`` 表示 ``ü``
  305. :param neutral_tone_with_five: 是否使用 ``5`` 标识轻声
  306. :param kwargs: 用于兼容老版本的 ``neutral_tone_with_5`` 参数,当传入
  307. ``neutral_tone_with_5`` 参数时,
  308. 将覆盖 ``neutral_tone_with_five`` 的值。
  309. :return: :py:attr:`~pypinyin.Style.TONE3` 风格的拼音
  310. Usage::
  311. >>> from pypinyin.contrib.tone_convert import tone_to_tone3
  312. >>> tone_to_tone3('zhōng')
  313. 'zhong1'
  314. >>> tone_to_tone3('shang')
  315. 'shang'
  316. >>> tone_to_tone3('shang', neutral_tone_with_five=True)
  317. 'shang5'
  318. >>> tone_to_tone3('lüè')
  319. 'lve4'
  320. >>> tone_to_tone3('lüè', v_to_u=True)
  321. 'lüe4'
  322. """
  323. if kwargs.get('neutral_tone_with_5', None) is not None:
  324. neutral_tone_with_five = kwargs['neutral_tone_with_5']
  325. tone3 = converter.to_tone3(tone)
  326. s = _improve_tone3(tone3, neutral_tone_with_five=neutral_tone_with_five)
  327. return _v_to_u(s, v_to_u)
  328. def tone2_to_normal(tone2, v_to_u=False):
  329. """将 :py:attr:`~pypinyin.Style.TONE2` 风格的拼音转换为
  330. :py:attr:`~pypinyin.Style.NORMAL` 风格的拼音
  331. :param tone2: :py:attr:`~pypinyin.Style.TONE2` 风格的拼音
  332. :param v_to_u: 是否使用 ``ü`` 代替原来的 ``v``,
  333. 当为 False 时结果中将使用 ``v`` 表示 ``ü``
  334. :return: Style.NORMAL 风格的拼音
  335. Usage::
  336. >>> from pypinyin.contrib.tone_convert import tone2_to_normal
  337. >>> tone2_to_normal('zho1ng')
  338. 'zhong'
  339. >>> tone2_to_normal('lüe4')
  340. 'lve'
  341. >>> tone2_to_normal('lüe4', v_to_u=True)
  342. 'lüe'
  343. """
  344. s = _re_number.sub('', tone2)
  345. s = _v_to_u(s, v_to_u)
  346. return _fix_v_u(tone2, s, v_to_u=v_to_u)
  347. def tone2_to_tone(tone2):
  348. """将 :py:attr:`~pypinyin.Style.TONE2` 风格的拼音转换为
  349. :py:attr:`~pypinyin.Style.TONE` 风格的拼音
  350. :param tone2: :py:attr:`~pypinyin.Style.TONE2` 风格的拼音
  351. :return: Style.TONE 风格的拼音
  352. Usage::
  353. >>> from pypinyin.contrib.tone_convert import tone2_to_tone
  354. >>> tone2_to_tone('zho1ng')
  355. 'zhōng'
  356. """
  357. regex = re.compile(RE_TONE2.pattern.replace('$', ''))
  358. d = phonetic_symbol.phonetic_symbol_reverse
  359. string = tone2.replace('ü', 'v').replace('5', '').replace('0', '')
  360. def _replace(m):
  361. s = m.group(0)
  362. return d.get(s) or s
  363. return regex.sub(_replace, string).replace('v', 'ü')
  364. def tone2_to_tone3(tone2, v_to_u=False):
  365. """将 :py:attr:`~pypinyin.Style.TONE2` 风格的拼音转换为
  366. :py:attr:`~pypinyin.Style.TONE3` 风格的拼音
  367. :param tone2: :py:attr:`~pypinyin.Style.TONE2` 风格的拼音
  368. :param v_to_u: 是否使用 ``ü`` 代替原来的 ``v``,
  369. 当为 False 时结果中将使用 ``v`` 表示 ``ü``
  370. :return: :py:attr:`~pypinyin.Style.TONE3` 风格的拼音
  371. Usage::
  372. >>> from pypinyin.contrib.tone_convert import tone2_to_tone3
  373. >>> tone2_to_tone3('zho1ng')
  374. 'zhong1'
  375. >>> tone2_to_tone3('lüe4')
  376. 'lve4'
  377. >>> tone2_to_tone3('lüe4', v_to_u=True)
  378. 'lüe4'
  379. """
  380. tone3 = RE_TONE3.sub(r'\1\3\2', tone2)
  381. return _fix_v_u(tone2, tone3, v_to_u=v_to_u)
  382. def tone3_to_normal(tone3, v_to_u=False):
  383. """将 :py:attr:`~pypinyin.Style.TONE3` 风格的拼音转换为
  384. :py:attr:`~pypinyin.Style.NORMAL` 风格的拼音
  385. :param tone3: :py:attr:`~pypinyin.Style.TONE3` 风格的拼音
  386. :param v_to_u: 是否使用 ``ü`` 代替原来的 ``v``,
  387. 当为 False 时结果中将使用 ``v`` 表示 ``ü``
  388. :return: :py:attr:`~pypinyin.Style.NORMAL` 风格的拼音
  389. Usage::
  390. >>> from pypinyin.contrib.tone_convert import tone3_to_normal
  391. >>> tone3_to_normal('zhong1')
  392. 'zhong'
  393. >>> tone3_to_normal('lüe4')
  394. 'lve'
  395. >>> tone3_to_normal('lüe4', v_to_u=True)
  396. 'lüe'
  397. """
  398. s = _re_number.sub('', tone3)
  399. s = _v_to_u(s, v_to_u)
  400. return _fix_v_u(tone3, s, v_to_u=v_to_u)
  401. def tone3_to_tone(tone3):
  402. """将 :py:attr:`~pypinyin.Style.TONE3` 风格的拼音转换为
  403. :py:attr:`~pypinyin.Style.TONE` 风格的拼音
  404. :param tone3: :py:attr:`~pypinyin.Style.TONE3` 风格的拼音
  405. :return: :py:attr:`~pypinyin.Style.TONE` 风格的拼音
  406. Usage::
  407. >>> from pypinyin.contrib.tone_convert import tone3_to_tone
  408. >>> tone3_to_tone('zhong1')
  409. 'zhōng'
  410. """
  411. tone2 = tone3_to_tone2(tone3, v_to_u=True)
  412. return tone2_to_tone(tone2)
  413. def tone3_to_tone2(tone3, v_to_u=False):
  414. """将 :py:attr:`~pypinyin.Style.TONE3` 风格的拼音转换为
  415. :py:attr:`~pypinyin.Style.TONE2` 风格的拼音
  416. :param tone3: :py:attr:`~pypinyin.Style.TONE3` 风格的拼音
  417. :param v_to_u: 是否使用 ``ü`` 代替原来的 ``v``,
  418. 当为 False 时结果中将使用 ``v`` 表示 ``ü``
  419. :return: :py:attr:`~pypinyin.Style.TONE2` 风格的拼音
  420. Usage::
  421. >>> from pypinyin.contrib.tone_convert import tone3_to_tone2
  422. >>> tone3_to_tone2('zhong1')
  423. 'zho1ng'
  424. >>> tone3_to_tone2('lüe4')
  425. 'lve4'
  426. >>> tone3_to_tone2('lüe4', v_to_u=True)
  427. 'lüe4'
  428. """
  429. no_number_tone3 = tone3_to_normal(tone3)
  430. mark_index = right_mark_index(no_number_tone3)
  431. if mark_index is None:
  432. mark_index = len(no_number_tone3) - 1
  433. before = no_number_tone3[:mark_index + 1]
  434. after = no_number_tone3[mark_index + 1:]
  435. number = _get_number_from_pinyin(tone3)
  436. if number is None:
  437. return tone3
  438. s = '{}{}{}'.format(before, number, after)
  439. return _fix_v_u(tone3, s, v_to_u=v_to_u)
  440. def _improve_tone3(tone3, neutral_tone_with_five=False):
  441. number = _get_number_from_pinyin(tone3)
  442. if number is None and neutral_tone_with_five and tone3 != '':
  443. tone3 = '{}5'.format(tone3)
  444. return tone3
  445. def _get_number_from_pinyin(pinyin):
  446. numbers = _re_number.findall(pinyin)
  447. if numbers:
  448. number = numbers[0]
  449. else:
  450. number = None
  451. return number
  452. def _v_to_u(pinyin, replace=False):
  453. if not replace:
  454. return pinyin
  455. return pinyin.replace('v', 'ü')
  456. def _fix_v_u(origin_py, new_py, v_to_u):
  457. if not v_to_u:
  458. return new_py.replace('ü', 'v')
  459. return _v_to_u(new_py, replace=True)