バリケンのPython日記 RSSフィード

2008-07-03

[] 文字列(4)  文字列(4) - バリケンのPython日記 を含むブックマーク はてなブックマーク -  文字列(4) - バリケンのPython日記  文字列(4) - バリケンのPython日記 のブックマークコメント

フォーマット文字列

Rubyには「文字列への式の埋め込み」という機能があって、があって、たとえば

C:\>irb
irb(main):001:0> a = ['Ruby', 'Python']
=> ["Ruby", "Python"]
irb(main):002:0> "Hello, #{a[0]}"
=> "Hello, Ruby"
irb(main):003:0> "Hello, #{a[1]}"
=> "Hello, Python"
irb(main):004:0>

のような感じで、文字列に簡単に値を埋め込むことができるんだけど、Pythonでも同じようなことをやろうと思ったら「フォーマット文字列」を使えばいいみたいだよ。

フォーマット文字列は、「フォーマット文字列 % (値1, 値2, ...)」のように書くよ。こうすると、C言語のsprintfのようにフォーマット文字列に値を埋め込んだ文字列を作ることが出来るよ。

>>> 'Hello, %s! Enjoy, %s!' % ('Python', 'Ruby')
'Hello, Python! Enjoy, Ruby!'
>>>

上記のフォーマット文字列中に出てくる「%s」は「文字列」を意味しているよ。そのほか「%d」は整数を表すよ。

>>> '%d + %d = %d' % (2, 3, 2 + 3)
'2 + 3 = 5'
>>>

こうしたフォーマット文字列で指定できる値はいろいろあるみたいだから、詳しくはPythonリファレンスマニュアルの「文字列フォーマット操作」を参照してね。

フォーマット文字列は、「フォーマット文字列 % {'キーワード1': 値1, 'キーワード2': 値2, ...}」という書式で書くこともできるよ。こうすると、フォーマット文字列に値の埋め込むときにキーワードを指定することができるよ。たとえば、

>>> '%(who)s is %(age)d years old.' % {'who': 'Taro', 'age': 10}
'Taro is 10 years old.'
>>>

のように書くことが出来るよ。

キーワードをつけると、値の順序を気にせずフォーマット文字列を書くことが出来るというメリットがあるよ。たとえば、次のようにさっきの'who'と'age'を入れ替えても、結果は同じになるよ。

>>> '%(who)s is %(age)d years old.' % {'age': 10, 'who': 'Taro'}
'Taro is 10 years old.'
>>>

ちなみに、「(値1, 値2, ...)」という表現を「タプル」、「{'キーワード1': 値1, 'キーワード2': 値2, ...}」という表現を「辞書」って呼ぶみたいだけど、説明はまた今度。

[] 文字列(5)  文字列(5) - バリケンのPython日記 を含むブックマーク はてなブックマーク -  文字列(5) - バリケンのPython日記  文字列(5) - バリケンのPython日記 のブックマークコメント

フォーマット文字列だけじゃなくて、Rubyのように文字列に対していろいろなメソッド呼び出しをすることによって、新たな文字列を生成することができるよ。

たとえば文字列に対してrjust()メソッド、ljust()メソッド、center()メソッドを呼び出すと、元の文字列に空白を追加して、引数で与えた文字数の固定長文字列を生成するよ。

空白の追加される場所は、rjust()メソッドは左側、ljust()メソッドは右側、center()メソッドは両側だよ。説明だけ聞いてもよく分らないと思うから、実際にメソッドを呼び出してその戻り値を見てみよう!

>>> "abc".rjust(10)
'       abc'
>>> "abc".ljust(10)
'abc       '
>>> "abc".center(10)
'   abc    '
>>> 

あと、rjust()メソッドと動作が似ているzfill()メソッドがあるよ。zfill()メソッドは空白じゃなくてゼロで埋めて固定長文字列を生成するよ。あと、整数(int型の値)を文字列に変換するにはstr()関数を使うよ。

>>> "abc".zfill(10)
'0000000abc'
>>> str(345).zfill(5)
'00345'
>>>

元の文字列の文字数が引数で与えた数よりも長い場合は、元の値がそのまま返るから、本当に固定長の文字列が欲しい時は注意してね。

>>> "hogehoge".rjust(3)
'hogehoge'
>>> "hogehoge".ljust(3)
'hogehoge'
>>> "hogehoge".center(3)
'hogehoge'
>>> "hogehoge".zfill(3)
'hogehoge'
>>>

ちなみに、rjust()メソッド、ljust()メソッド、zfill()メソッドに相当するフォーマット文字列もあるよ。詳しくはPythonリファレンスマニュアルの「文字列フォーマット操作」を参照してね。必要に応じて、メソッド操作とフォーマット文字列を使い分けてね。

>>> "abc".rjust(10)
'       abc'
>>> '%10s' % 'abc'
'       abc'
>>> "abc".ljust(10)
'abc       '
>>> '%-10s' % 'abc'
'abc       '
>>> str(345).zfill(5)
'00345'
>>> '%05d' % 345
'00345'
>>>

そのほか、高林さんのブログのエントリ「文字列操作の比較表: Ruby, Python, JavaScript, Perl, C++」が文字列操作の参考になるよ。

[] Unicode文字列(1)  Unicode文字列(1) - バリケンのPython日記 を含むブックマーク はてなブックマーク -  Unicode文字列(1) - バリケンのPython日記  Unicode文字列(1) - バリケンのPython日記 のブックマークコメント

Pythonには普通の文字列のほかに、「Unicode文字列」というのがあるよ。Unicode文字列は、普通のシングルクォートやダブルクォートで囲って表現する文字列の前にuをつけると生成できるよ。

>>> u'abc'
u'abc'
>>> type(u'abc')
<type 'unicode'>
>>>

Unicode文字列は「unicode型」なんだね。

あと、unicode()関数を使ってもUnicode文字列を生成できるよ。第二引数で指定している「"shift_jis"」は、現在のスクリプトのエンコードがシフトJISであるということを明示しているよ。

s = unicode("こんにちは", "shift_jis")

Unicode文字列を使うと、日本語などの多バイト文字の文字数もきちんと数えることが出来るよ。

>>> s = 'こんにちは'
>>> len(s)
10
>>> s = u'こんにちは'
>>> len(s)
5
>>>

Unicode文字列を他のエンコードに変更するには、encode()メソッドを使うよ。

>>> s = u'こんにちは'
>>> print s.encode('shift_jis')
こんにちは
>>>

[] Unicode文字列(2)  Unicode文字列(2) - バリケンのPython日記 を含むブックマーク はてなブックマーク -  Unicode文字列(2) - バリケンのPython日記  Unicode文字列(2) - バリケンのPython日記 のブックマークコメント

エンコード宣言

Pythonスクリプトファイルの1行目か2行目に「# -*- coding: エンコード名 -*-」と書いておくと、そのPythonスクリプトファイルで使用しているエンコードを指定できるよ。これを「エンコード宣言」って言うみたい。

エンコード宣言をしておくとソースコード中に日本語を直接書くことができるから、Unicode文字列を使う場合は必ず指定するようにしたほうがいいみたい。

たとえば「# -*- coding: utf-8 -*-」と書いておくと、そのスクリプトの文字コードがUTF-8だとみなされるよ。同様に「# -*- coding: euc-jp -*-」ならスクリプトの文字コードはEUC、「# -*- coding: shift-jis -*-」ならスクリプトの文字コードはShift_JISだとみなされるよ。

そのほか日本語を使うときは「Python でUTF-8, shift_jis, euc_jpなど日本語を使う方法」が参考になると思うよ。

anotheranother2008/07/04 22:58「Unicode文字列(2)」は、pythonではなくemacsの話では?

muscovyduckmuscovyduck2008/07/05 11:01いえ、Emacs限定の話ではなく、Pythonの話ですよ。
詳しくは下記をどうぞ。
http://www.python.jp/doc/2.4/ref/encodings.html

トラックバック - http://python.g.hatena.ne.jp/muscovyduck/20080703