Go to list of users who liked
Share on X(Twitter)
Share on Facebook
More than 3 years have passed since last update.
Pythonにおける基本的な文字列操作をまとめました。経験豊富な人には物足りない内容かもしれませんが...
(追記2018.12.23:print の文法をPython3対応にしました。Python2でコピペしたコードが動かない場合はfrom __future__ import print_function をコード辺の先頭に入れてください。)
Pythonの文字列 = immutable(変更不能)
Pythonの文字列はimmutableなので、部分的に書き換えたいというような場合でも、
新しい文字列オブジェクトとして組み立てることになります。
たとえば、文字列置換をおこなうreplaceというメソッドは置換したあとの内容をもつ別の文字列オブジェクトを返します。
連結
連結には+演算子を使います。
a='Python'b='2.7'c=a+bprint(c)# => 'Python2.7'順番に処理されるのでたくさん連結してもok
a='Python'b=' is'c='fancy'print(a+b+c)# => 'Python is fancy'joinメソッドとリスト/タプルを使って連結するテクニックもありますね。
余談ですがRubyのjoinはArrayのメソッド(連結文字列を引数にとる)、Pythonのjoinはstrのメソッド(list/tupleを引数にとる)と、逆になっているのでRubyの経験が豊富な方は注意が必要です。
strings=['dog','cat','penguin']print(','.join(strings))#=> 'dog,cat,penguin'繰り返し
同じ内容を繰り返す場合は*演算子で整数を与えると指定した回数だけリピートした文字列が生成されます。
s='dog?'print(s*3)#=> 'dog?dog?dog?'値の埋め込み
文字列に変数の値を展開する際には、3つのやり方があります。もしかしたら私が知らないだけで他にもあるかもしれません。
- sprintfスタイル:
'%s, %s' % ('Hello', 'World') - 拡張sprintfスタイル:
'%(a)s, %(b)s' % dict(a='Hello', b='World') - formatメソッド利用:
'{0}, {1}'.format('Hello', 'World')
(注) 二つ目の正確な呼び名はよくわからないのですが、ここでは勝手に拡張sprintfスタイルと呼ぶことにしました。
sprintfスタイル
文字列に% 演算子で値またはlist/tupleを与えると以下のように展開できます。
a='Python'b='a programming language'print('%s is %s'%(a,b))# => 'Python is a programming language'c='World'print('Hello, %s!'%c)# => 'Hello, World!'文字列中の展開記号(%sなど)の個数の数だけ、与える値も必要です。多くても少なくてもいけません。展開記号が1つの場合は%のあとの値はlist/tupleにする必要はありません。(1要素のlist/tupleでも展開されます) 上の例だと最初のprint文のテンプレート文字列は展開記号%sを2つ含むので、%の後にくる値で与えるタプルの要素の数も2つになっています。テンプレート文字列中で、%という文字自体を文字として残したい場合は%%と'%'2文字にするとよい です。
以下のようなフォーマット指定子があります。よくわからないうちはとりあえず%sにしておくというのも手かもしれません。フォーマット指定子の書き方はprintfのwikipediaページなどに説明を譲りたいと思います。
%s- 文字列として展開%d- 整数として展開%f- 小数点数として展開
タプルやリストを'(1, 2, 3)' のような文字列として展開してほしいときは
tuple_var=(1,2,3)print('tuple_var is: %s'%(tuple_var,))としないと3個あるのに置換先のプレースホルダが1個しかないよ!みたいに怒られてしまうので注意ですね。
拡張sprintfスタイル
※拡張sprintfスタイルというのは私が勝手につけた名前です(^^;
フォーマット文字列の%のあとに丸カッコでかこってdictオブジェクトのキーを指定し、フォーマット文字列に対して%演算子の右辺にdictオブジェクトを指定します。繰り返し同じ値を埋め込む際、すでにdict変数がある場合などに便利でしょう。
v=dict(first='Michael',family='Jackson')print('He is %(first)s, %(first)s %(family)s.'%v)formatメソッドの利用
formatメソッドを使うことでformatメソッド専用のテンプレート言語を使うことができます。
print('{0}, {1}'.format('Hello','World'))#=> 'Hello, World'詳しくは書式指定ミニ言語仕様を見て見てください。
置換(replace)
s='Today is Monday.'ss=s.replace('Monday','Sunday')#=> 'Today is Sunday.'print(ss)s2='Hello Hello'ss2=s2.replace('Hello','Bye')#=> 'Bye Bye' 第三引数を指定しなければすべて置換されるprint(ss2)s3='World World'ss3=s3.replace('World','Hello',1)#=> 'Hello World' # 第三匹数で置換する個数を指定print(ss3)あるパターンに従って文字列を置換する、といった処理はre(正規表現)パッケージのsubメソッドを使います。
importres='Hello World'print(re.sub(r"[a-z]","A",s))#=> 'HAAAA WAAAA'N文字目の文字の取得
s='abc'n=1# 'a'がほしいprint(s[n-1])# 0ベースインデックスで文字を取得s2='xyz'print(s[-1])# 'z' 最後の文字部分文字列の取得(N文字目から、M文字とりだす)
s="This is a pen."n=1m=4print(s[n-1:n-1+m])# 'This'print(s[0:4])# 'This'print(s[-4:-1])# 'pen'検索
findを使います。後ろ向きに検索したいときはrfindが使えます。
findは該当文字列が見つかれば0からはじまる文字列位置を, 見つからなければ-1を返します。
s='abcabcabc'index=s.find('b')# indexは1(2文字目)第二引数で検索を開始する位置を指定できます。
s='abcabcabc'index=s.find('b',2)# indexは4(5文字目)以下のようなコードで文字列中からすべてのターゲットを探し出せます。
s='abcabcabc'target='b'index=-1whileTrue:index=s.find(target,index+1)ifindex==-1:breakprint('start=%d'%index)1文字ずつ処理
string型はイテレータでもあるので、以下のようにforで処理できます。文字のlistが欲しければlist(strvalue)でいいですね。
forcin'aiueo':print(c)print(list('hoge'))# => ['h', 'o', 'g', 'e']インデックスで文字を参照しながら取り出すというやり方もあるかもしれません。
s='aiueo'foriinrange(len(s)):c=s[i]print(c)両端の空白削除
strip,lstrip,rstripが使えます。
stripは両端からスペース・タブ文字・改行(\rおよび\n)を削除した文字列を、
lstripはstripと同等の処理を左端のみに適用したものを、
rstripはstripと同等の処理を右端のみに適用したものを返します。
s=' x'print('A'+s.strip()+'B')# => 'AxB'print('A'+s.lstrip()+'B')# => 'Ax B'print('A'+s.rstrip()+'B')# => 'A xB'改行削除(perlやrubyのchomp相当の処理)
rstripでいけそうです。ただ末尾に空白と改行がある2パターンがあり、改行の場合だけ削除したい、というような場合は引数で削除対象の文字を指定する必要があります。
line='hoge\n'msg=line.rstrip()+'moge'print(msg)# => 'hogemoge'withopen('./test.txt')asfh:forlineinfh:no_line_break_line=line.rstrip()# なにかする# 空白は削除せずに改行だけ削除するline_with_space='line\n'# 改行の前の空白は削除したくないprint(line_with_space.rstrip('\n'))# => 'line '全部大文字にする
upper()メソッドを使います。
print('hello'.upper())# => 'HELLO'全部小文字にする
lower()メソッドを使います。
print('BIG'.lower())# => 'big'ある文字列が部分文字列として含まれるかどうか調べる
s='abc'print('b'ins)#=> Trueprint('x'ins)#=> Falseある文字列が部分文字列として登場する回数を数える
先ほど出てきたfindメソッドを使って自力でやってもよいですが、countという便利なメソッドがあります。
s='aaabbc'print(s.count('b'))#=> 2intを文字列に変換する
v=1print(str(v))print('%d'%v)floatを文字列に変換する
f=1.234print(str(f))#=> '1.234'print('%f'%f)#=> '1.234000'listを文字列に変換する, tupleを文字列に変換する
変換というか、デバッグprintなどで文字列で表現したいことはありますよね。
v=[1,2,3]print(str(v))#=> '[1, 2, 3]'print('%s'%v)#=> '[1, 2, 3]'tuple1つを%sで表示しようとすると, Pythonが与えられたtupleをテンプレート用の値のリストと解釈してエラーになってしまいます。
v=(1,2,3)print(str(v))#=> '(1, 2, 3)' よい例print('%s'%v)#=> '(1, 2, 3)'を期待するが、TypeErrorになってしまうprint('%s'%(v,))#=> '(1, 2, 3)' よい例joinなどを使って組み立ててみるのもいいですね。
v=[1,2,3]print('<'+('/'.join([str(item)foriteminv]))+'>')#=> '<1/2/3>'tupleオブジェクトも同様です。
dictを文字列に変換する
変換というか、デバッグprintなどで文字列で表現したいことはありますよね。
v=dict(a=1,b=2)print(str(v))#=> "{'a': 1, 'b': 2}"print('%s'%v)#=> "{'a': 1, 'b': 2}"keysやリスト内包表記、joinを使ってワンライナーで文字列生成してもいいですね。
v=dict(a=1,b=2)print('<'+','.join(['%s=%s'%(k,v[k])forkinv.keys()])+'>')#=> '<a=1, b=2>'バイト列(bytes)をunicode文字列にする
(バイナリモードでオープンされた)ファイルやソケットから読み込んだデータはそのままだとバイト列なので、unicode文字列に解釈してあげないと文字単位の操作がうまくできません。Python2系(2.7など)ではstr(バイト列)とunicode(文字列)は区別されており、Webアプリケーショなど入力にマルチバイト文字が想定されるシーンでは文字列はunicodeオブジェクトとして扱ったほうがよいでしょう。バイト列をエンコーディングを指定してunicode文字列として解釈するためにはdecode()メソッドを使います。
Python3系ではstr 型が文字列型(Python2系のunicode型に相当),bytes 型がバイト列型(Python2系のstr型に相当)となっています。
withopen('utf8_content_file.txt','rb')asfh:# rbなのでバイナリモードbyte_content=fh.read()# ぜんぶ読み込む, この時点ではバイト列print(len(byte_content))# バイト数unicode_string=byte_content.decode('utf-8')# utf-8エンコーディングで、文字の並びとして解釈print(len(unicode_string))# 文字数decode() メソッドのデフォルトエンコーディングはutf-8 なので解釈対象のバイト列のエンコーディングがUTF-8だとわかっている場合はエンコーディングを省略してもよいでしょう。
bytes_data = b'\xe3\x83\x90\xe3\x82\xa4\xe3\x83\x88\xe5\x88\x97'print(bytes_data.decode()) # => 'バイト列'日本語でよく使われるencodingを以下に列挙しておきます。
utf_8UTF-8 (別名:utf-8U8utf8cp65001)shift_jisシフトJIS (別名:csshiftjisshiftjissjiss_jis)cp932シフトJIS(拡張シフトJIS) (別名:932ms932mskanjimks-kanji)euc_jpEUC-JP (別名:eucjpujisu-jis)iso2022_jpJIS(ISO-2022-JP) (別名:csiso2022jpiso2022jpiso-2022-jp)
その他にPythonが対応しているエンコーディングはcodecs パッケージのページで見ることができます:https://docs.python.org/ja/3/library/codecs.html
unicode文字列をバイト列(bytes)にする
逆に(バイナリモードでオープンされた)ファイルやソケットに書き込むとき、文字列をバイト列にしないといけないです。そういうときはunicodeオブジェクトのencode()メソッドをつかいます。
unicode_string=u'マルチバイト文字の文字列'withopen('./utf8_content_file.txt','wb')asfh:# 書き込み+バイナリモードでopenbyte_content=unicode_string.encode('utf-8')# utf-8エンコーディングで表現した場合のバイト列を取得fh.write(byte_content)# バイト列を書き込みencode() メソッドもをエンコーディングを渡さないとutf-8 を渡されたのと等価の挙動をします。
str_data='バイト列'print(str_data.encode())# => b'\xe3\x83\x90\xe3\x82\xa4\xe3\x83\x88\xe5\x88\x97'テンプレートエンジンを使う
テンプレートエンジンは機能がとても豊富なのでここではいくつかのメジャーなライブラリの紹介にとどめます。
jinja2が一番メジャーでしょうか.
参考リンク
Register as a new user and use Qiita more conveniently
- You get articles that match your needs
- You can efficiently read back useful information
- You can use dark theme
