string – テキストを扱う

目的:テキストを扱う定数やクラスを提供する
利用できるバージョン:2.5

string モジュールは Python の初期バージョンを端緒とします。バージョン 2.0 では、このモジュールのみに実装されていた多くの関数が strunicode オブジェクトのメソッドに移行されました。そういった関数のレガシーバージョンはまだ有効ですが、その使用は非推奨であり Python 3.0 で削除されます。それでも string モジュールは、文字列やユニコードオブジェクトを扱う便利な定数やクラスを提供します。そして、この記事はそういった内容に特化しています。

定数

string モジュールの定数は、 ascii_lettersdigits のような特殊な特性のカテゴリで使用されます。定数によっては、 lowercase のようにロケールに依存するので、その値はユーザの言語設定を考慮して変更します。一方 hexdigits のような定数は、ロケールが違っても変更する必要はありません。

import string

for n in dir(string):
    if n.startswith('_'):
        continue
    v = getattr(string, n)
    if isinstance(v, basestring):
        print '%s=%s' % (n, repr(v))
        print

ほとんどの定数の名前は自己説明的です。

$ python string_constants.py
ascii_letters='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'

ascii_lowercase='abcdefghijklmnopqrstuvwxyz'

ascii_uppercase='ABCDEFGHIJKLMNOPQRSTUVWXYZ'

digits='0123456789'

hexdigits='0123456789abcdefABCDEF'

letters='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'

lowercase='abcdefghijklmnopqrstuvwxyz'

octdigits='01234567'

printable='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'

punctuation='!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'

uppercase='ABCDEFGHIJKLMNOPQRSTUVWXYZ'

whitespace='\t\n\x0b\x0c\r '

関数

string モジュールから移行されなかった2つの関数があります。 capwords() は文字列の全ての単語の先頭を大文字にします。

import string

s = 'The quick brown fox jumped over the lazy dog.'

print s
print string.capwords(s)

文字列を split() して、その出力リストの単語の先頭を大文字にしてから、 join() でそれらの単語を結合するのと同じ結果です。

$ python string_capwords.py
The quick brown fox jumped over the lazy dog.
The Quick Brown Fox Jumped Over The Lazy Dog.

もう1つの関数は、文字セットを別のものに変更する translate() メソッドで使用される変換テーブルを作成します。

import string

leet = string.maketrans('abegiloprstz', '463611092572')

s = 'The quick brown fox jumped over the lazy dog.'

print s
print s.translate(leet)

このサンプルでは、文字が l33t による数字で置き換えられます。

$ python string_maketrans.py
The quick brown fox jumped over the lazy dog.
Th3 qu1ck 620wn f0x jum93d 0v32 7h3 142y d06.

テンプレート

文字列テンプレートが PEP 292 の一部として Python 2.4 で追加されました。それは組み込みの補間構文の代替方法を意図しています。 string.Template の補間では、変数は $ (例 $var) を接頭辞とする名前で識別されます。また、変数名の周りの文字列を無効にする必要があるなら、変数名を中括弧で囲むこともできます(例 ${var})。

このサンプルは、シンプルなテンプレートと同じような文字列の補間設定を比較します。

import string

values = { 'var':'foo' }

t = string.Template("""
$var
$$
${var}iable
""")

print 'TEMPLATE:', t.substitute(values)

s = """
%(var)s
%%
%(var)siable
"""

print 'INTERPLOATION:', s % values

ご覧の通り、両方のケースでトリガー文字 ($%) は2文字続けることでエスケープされます。

$ python string_template.py
TEMPLATE:
foo
$
fooiable

INTERPLOATION:
foo
%
fooiable

テンプレートと標準の文字列補間の大きな違いの1つは、引数の型を考慮しない点です。その値は文字列に変換されて、その変換された文字列は結果出力に追加されます。フォーマットオプションは指定しなくても構いません。例えば、浮動小数を表す数値の桁数を管理する方法はありません。

safe_substitute() を使用することの利点でもありますが、テンプレートが要求する全ての値が引数として提供されない場合でも例外を発生させません。

import string

values = { 'var':'foo' }

t = string.Template("$var is here but $missing is not provided")

try:
    print 'TEMPLATE:', t.substitute(values)
except KeyError, err:
    print 'ERROR:', str(err)
    
print 'TEMPLATE:', t.safe_substitute(values)

values ディクショナリには missing の値はないので、 substitute()KeyError を発生させます。 safe_substitute() は、このエラーを発生させずに捕捉して、テキストに変数表現がそのまま残ります。

$ python string_template_missing.py
TEMPLATE: ERROR: 'missing'
TEMPLATE: foo is here but $missing is not provided

高度なテンプレート

string.Template のデフォルトの構文が好みではないなら、テンプレート本文の変数名を見つける正規表現を調整することでその振る舞いを変更できます。最も簡単な方法は delimiteridpattern のクラス属性を変更します。

import string

class MyTemplate(string.Template):
    delimiter = '%'
    idpattern = '[a-z]+_[a-z]+'

t = MyTemplate('%% %with_underscore %notunderscored')
d = { 'with_underscore':'replaced', 
      'notunderscored':'not replaced',
      }

print t.safe_substitute(d)

このサンプルでは、変数の ID は中間にアンダースコアを含めなければならないので、 %notunderscored は置き換えられません。

$ python string_template_advanced.py
% replaced %notunderscored

もっと複雑な変更だと、 pattern 属性をオーバーライドして全く新しい正規表現を定義できます。そのパターンは、エスケープされるデリミタ、名前付き変数、括弧付きの名前付き変数、不正なデリミタパターンの4つの名前付きグループを含めなければなりません。

デフォルトのパターンを見てみましょう。

import string

t = string.Template('$var')
print t.pattern.pattern

t.pattern は複雑な正規表現なので、実際の文字列を見るためにその pattern 属性にアクセスする必要があります。

$ python string_template_defaultpattern.py

    \$(?:
      (?P<escaped>\$) |   # Escape sequence of two delimiters
      (?P<named>[_a-z][_a-z0-9]*)      |   # delimiter and a Python identifier
      {(?P<braced>[_a-z][_a-z0-9]*)}   |   # delimiter and a braced identifier
      (?P<invalid>)              # Other ill-formed delimiter exprs
    )

例えば、変数の構文として {{var}} といったテンプレートの新しい型を作成したいなら、次のようなパターンを使用できます。

import re
import string

class MyTemplate(string.Template):
    delimiter = '{{'
    pattern = r'''
    \{\{(?:
    (?P<escaped>\{\{)|
    (?P<named>[_a-z][_a-z0-9]*)\}\}|
    (?P<braced>[_a-z][_a-z0-9]*)\}\}|
    (?P<invalid>)
    )
    '''
    
t = MyTemplate('''
{{{{
{{var}}
''')

print 'MATCHES:', t.pattern.findall(t.template)
print 'SUBSTITUTED:', t.safe_substitute(var='replacement')

変数名と括弧付きの変数名のパターンが同じだったとしても、両方とも提供する必要があります。実行結果は次のようになります。

$ python string_template_newsyntax.py
MATCHES: [('{{', '', '', ''), ('', 'var', '', '')]
SUBSTITUTED:
{{
replacement

非推奨な関数

非推奨なメソッドの情報は stringunicode クラスへ移行されました。 String メソッド のドキュメントを参照してください。

See also

string
本モジュールの標準ライブラリドキュメント
PEP 292
シンプルな文字列置換

テキスト処理ツール

Bookmark and Share