読者です 読者をやめる 読者になる 読者になる

Pythonで文字列を1文字ずつ分割する

PHP Python

シングルバイト文字の場合こちらのサイトを参考に解決しましたが、

マルチバイト文字ではどうなるのか疑問が生じたので方法を調べてみました。

目次

文字列を1文字ずつ分割する

PHP preg_split

普段はPHPを利用していますので、参考までにPHPではpreg_splitで行えることを記載します。

シングルバイト文字

<?php
$chars = preg_split('//', 'abcdef', -1, PREG_SPLIT_NO_EMPTY);
print_r($chars);
/*
Array
(
    [0] => a
    [1] => b
    [2] => c
    [3] => d
    [4] => e
    [5] => f
)
*/

マルチバイト文字(UTF-8)

<?php
$chars = preg_split('//u', 'あいうえお', -1, PREG_SPLIT_NO_EMPTY);
print_r($chars);
/*
Array
(
    [0] => あ
    [1] => い
    [2] => う
    [3] => え
    [4] => お
)
*/

Python

2系も3系もlistを用いることで文字列を分割できる模様。
2系と3系でマルチバイト文字の取り扱いが少々異なるようです。

Python 2.x list

シングルバイト文字

chars = list('abcdef')
print chars
# ['a', 'b', 'c', 'd', 'e', 'f']

マルチバイト文字(UTF-8)

Python 2系では明示的にUnicode文字をあらわすu''としないと1byteずつ分割される模様。

  • list('あいうえお')
# -*- coding: utf-8 -*-
chars = list('あいうえお')
print chars
# ['\xe3', '\x81', '\x82', '\xe3', '\x81', '\x84', '\xe3', '\x81', '\x86', '\xe3', '\x81', '\x88', '\xe3', '\x81', '\x8a']
  • list(u'あいうえお')
# -*- coding: utf-8 -*-
chars = list(u'あいうえお')
chars = [char.encode('utf-8') for char in chars]
print str(chars).decode('string-escape')
# ['あ', 'い', 'う', 'え', 'お']

for c in chars:
    print c
# あ
# い
# う
# え
# お

Python 3.x list

シングルバイト文字

chars = list('abcdef')
print(chars)
# ['a', 'b', 'c', 'd', 'e', 'f']

マルチバイト文字(UTF-8)

Windows7コマンドプロンプトで素直にprintしたところ期待するUTF-8ではなくShift_JISに変換されてしまいました。

  • これを避けるため、当初UTF-8のbytes型に変換した上sysモジュール経由で出力。
# -*- coding: utf-8 -*-
import sys

chars = list('あいうえお')
chars = [bytes(char, 'utf-8') for char in chars]
sys.stdout.buffer.writelines(chars)
# あいうえお

for char in chars:
    sys.stdout.buffer.write(char)
    sys.stdout.write('\n')
    sys.stdout.flush()
# あ
# い
# う
# え
# お
  • しかし、この現象はencodingの設定により起こるとのこと。
    当初の初期値。
print(sys.getdefaultencoding())
# utf-8
print(sys.stdout.encoding) # 出力がutf-8ではない
# cp932
  • 次の記事を参考に適切な文字コードsys.stdout.encodingに設定したところprintでもできました。

# -*- coding: utf-8 -*-
import sys, io
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')

chars = list('あいうえお')
print(chars)
# ['あ', 'い', 'う', 'え', 'お']

for char in chars:
    print(char)
# あ
# い
# う
# え
# お

マルチバイト文字はPython 3系の方が扱いやすいようです。