print()関数は与えられた引数のデータ型に応じて文字に変換してくれます。
しかし、数値を精度に応じた桁数で表示するなどデータを文字として出力する方法を
制御する必要にすぐに直面するでしょう。
ということで、今回は文字列(およびそれに関係したデータ型)の取り扱いについて学びます。
目標は、
__________________________________フィボナッチ数の数表_________________________________
00, 01, 02, 03, 04, 05, 06, 07, 08, 09
00: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55
10: 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765
20: 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229, 832040
という形で数表を印刷することです。
今日の講座では、数表の印刷 を例に
文字型(str)データのメソッド : .join(), .split() など
Unicode文字列(str)とバイト列(bytes) : u"abc" とb"abc"
文字列の整形(Format)
str型の.format()メソッド
フォーマット済み文字列定数: f""
などについて学びます。
n=0..29のフィボナッチ数列fib(n)の値を次のような形で印刷するPythonプログラムを作って見ましょう。
__________________________________フィボナッチ数の数表_________________________________
00, 01, 02, 03, 04, 05, 06, 07, 08, 09
00: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55
10: 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765
20: 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229, 832040
#プログラムと実行結果
def fib(n:int)->int:
if n == 0 or n == 1:
value= 1
else:
value= fib(n-1) + fib(n-2)
return value
def 数表の印刷():
print ("フィボナッチ数の数表".center(77,"_"))
print ( " {0}".format(
",".join((" {0:02d}".format(c) for c in range(10))))
)
for r in range(0,30,10):
print("{0:02d}:{1}".format(
r,
",".join(("{0:7d}".format(fib(c)) for c in range(r,r+10)))
))
if __name__ == "__main__": 数表の印刷()
__________________________________フィボナッチ数の数表_________________________________
00, 01, 02, 03, 04, 05, 06, 07, 08, 09
00: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55
10: 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765
20: 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229, 832040
str)型データのメソッド¶pythonのデータ型を処理するための固有の関数(メソッド)が定義されています。 これらのメソッドはいくつかの種類に大きく分けることができます。
.isascii(), .isdecimal(),.count(), .startwith()など.capitalize(), .center(), .strip(),.split(),.join()など.format(), .format_map()今回は、これらのメソッドの内、よく使うであろう幾つかの関数についてご説明します。
今回説明を省いたメソッドについては、 Pythonの標準ドキュメントの
Python 標準ライブラリ テキストシーケンス型 --- str
などが参考になるでしょう。
データ型がどのようなメソッドを持っているかを覗くにはdir()関数を、そのメソッドのつかいかたは、help()関数を使うのは、手軽な方法だと思います。
dir()関数はオブジェクトあるいはクラスのメソッドあるいはアトリビュートのリストを返します。
print(dir(str)) # dir("") でもおなじ
['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isascii', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'removeprefix', 'removesuffix', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
メソッドの名前だけでなく、使い方まで知りたい場合には、help()関数が役に立ちます。
help(str.center)
Help on method_descriptor:
center(self, width, fillchar=' ', /)
Return a centered string of length width.
Padding is done using the specified fill character (default is a space).
"フィボナッチ数の数表".center(77,"_")
'__________________________________フィボナッチ数の数表_________________________________'
str型データはユニコード文字¶Python3ではstr型は ユニコード文字が一列に並んだ物(ユニコード文字列)です。
ユニコード文字列定数 u"無限未来" と 文字列定数 "無限未来"は同じ同じ文字列を表します。
u"無限未来" == "無限未来"
True
| エスケープシーケンス | 意味 |
|---|---|
\N{name} |
Unicode データベース中で name という名前の文字 |
\uxxxx |
16-bit の十六進値 xxxx をユニコード コードポイントに持つ文字 |
\Uxxxxxxxx |
32-bit の十六進値 xxxxxxxx をユニコード コードポイントに持つ文字 |
ユニコード文字のコードポイントは、0x00〜0x10FFFFの範囲にあると規格により定義されています。
print ( "\N{RIGHT TRIANGLE}")
⊿
print("\\u{0:x}".format(ord("希")),"<->", "\u5e0c","<->","\U00005e0c")
\u5e0c <-> 希 <-> 希
import unicodedata
unicodedata.name("希"), "\N{CJK UNIFIED IDEOGRAPH-5E0C}"
('CJK UNIFIED IDEOGRAPH-5E0C', '希')
r"")¶タブ('\t')、改行('\n')などの制御文字を文字列中に挿入するためにエスケープ文字(エスケープシークエンス)を使います。エスケープ文字はほぼC言語と同じです。
| エスケープシーケンス | 意味 | \ | エスケープシーケンス | 意味 | |
|---|---|---|---|---|---|
\+newline |
バックスラッシュと改行文字が無視されます | | | \n |
ASCII 行送り(LF, NL, EOL, 0x0a) | |
\\ |
バックスラッシュ (\, REVERSE SOLIDUS, 0x5c) |
| | \r |
ASCII 復帰 (CR, 0x0d) | |
\' |
一重引用符 (', APOSTROPHE, 0x27) | | | \t |
ASCII 水平タブ (TAB, HT, 0x09) | |
\" |
二重引用符 (", QUOTATION MARK,0x22) | | | \v |
ASCII 垂直タブ (VT, 0x0b) | |
\a |
ASCII 端末ベル (BEL, 0x07) | | | \ooo |
8 進数値 ooo を持つ文字 | |
\b |
ASCII バックスペース (BS, 0x08) | | | \xhh |
16 進数値 hh を持つ文字 | |
\f |
ASCII フォームフィード (FF, 0x0c) | | |
raw文字列定数( r"..."あるいは R"...")を使って、エスケープシーケンスの働きを抑制して文字列定数を定義できます。
s="abc\
de\\f"
tqs="""abc
de\\f
"""
print (s,repr(s))
print (tqs,repr(tqs))
print ("str:","ab\\nc", "raw str:", r"ab\\nc")
f"{{v}} {s}".format(v="xyz")
abcde\f 'abcde\\f' abc de\f 'abc\nde\\f\n' str: ab\nc raw str: ab\\nc
'xyz abcde\\f'
.encode と .decode :ユニコード文字(str)とバイト列(bytes)の相互変換¶通信、機器操作などでは、ユニコード文字列をバイト列として表現することが必要になります。python3では、バイト列を取り扱うためのデータ型としてbytes型が用意されています。
.encode()メソッド。bytes型の.decode()メソッドを使います。bytearray型も.decode()メソッドを持っています。bytesへ: .encode¶u"新たな希望".encode("utf-8")
b'\xe6\x96\xb0\xe3\x81\x9f\xe3\x81\xaa\xe5\xb8\x8c\xe6\x9c\x9b'
出力の文字列がb'あるいはb"で始まっているのは、これがbytes列型であることを表しています。
print("\\u{0:x}".format(ord("希")),"<->", "\u5e0c" )
print("\\u{0:x}".format(ord("希")), "!=", "希".encode('utf-8'),
"!=", "希".encode('iso-2022-jp'),"!=", "希".encode('cp932'))
\u5e0c <-> 希 \u5e0c != b'\xe5\xb8\x8c' != b'\x1b$B4u\x1b(B' != b'\x8a\xf3'
bytesからユニコード文字列へ: .decode¶bytes型データをユニコードに変換するには、.decodeメソッドを使います。
b'\xe6\x96\xb0\xe3\x81\x9f\xe3\x81\xaa\xe5\xb8\x8c\xe6\x9c\x9b'.decode("utf-8")
'新たな希望'
joinとsplit:文字列の分解と結合¶"来た、見た、勝った".split("、")
['来た', '見た', '勝った']
"!!".join(['来た', '見た', '勝った'])
'来た!!見た!!勝った'
その他にも、.strip(),.justify(),.center(), .title, .upper(), .lower()などの文字列変換のメソッドが用意されています。これらのメソッドの戻り値は変換済みの新しい文字列です。 str型は不変(immutable)な型なので、これらの関数の実行で元の文字列は変更されずに、新しい文字列が作成されます。
s="abc"
print(s)
sc=s.center(40,"-")
print(sc)
abc ------------------abc-------------------
プログラムからデータを端末などの出力するには、データを文字列化する(整形)ことが必要です。
Python3で文字列の書式化(整形)にはいくつかの方法があります。
Python3での基本は.formatメソッドでを使う方法です。
.format()をもっと簡単に使うために、フォーマット済み文字列定数(f"" あるいはF"")がPython3.6で導入されました
Python2で使われていた%-書式もまだ利用可能です。
.format(): 書式指定文字列¶参照: https://docs.python.org/ja/3/library/stdtypes.html#str.format
文字列型データの.format()メソッドは、C言語のsprintfとおなじように、
複数のデータから出力用の整形された文字列を作成します。
例えば、"{0:d}".format(123)は文字列'123'を作りだします。
"{0:d}".format(123)
'123'
同じデータを異なった形式で整形することも可能です。ここでは、一つの引数を整数(d),浮動小数点(f)および指数形式(e)に
整形しています。(同じ入力データを書式指定文字列のなかで繰り返して使うことが可能です。)
"{0:d} {0:f} {0:e}".format(123)
'123 123.000000 1.230000e+02'
.format関数の引数¶.format関数には、変換対象となるデータを、位置引数あるいは名前付き引数として書き並べます。
変換指定文字列には引数に対応した{<指数>:<変換指定>} あるいは {<識別子>:<変換指定>}
した変換指定文字列が含まれます。
変換指定文字列では"{"および"}"が特別の意味を持ちます。変換された後の文字列に{あるいは} が含む場合には、
"{{" あるいは "}}"をその場所で使います。
"{1:s} {0:d} {x:f}".format(123, "abc", x=3.14)
'abc 123 3.140000'
同じ<指数>、<識別子>が複数回現れても良いのですが、現れる異なった指数は位置引数の数より小さくなくてはいけません。
また<識別子>は.formatの名前付き引数に現れていなければなりません。
同じデータを異なる変換指定を使うことで、異なった表現として印刷することができます。
"{0:d} {1:s} {x:f} {y:f} {x:e} {y:e}".format(123, "abc", x=3.14, y=2.71)
'123 abc 3.140000 2.710000 3.140000e+00 2.710000e+00'
<変換指定>は一般に次の形を持っています。
[[<フィル文字>]<整列指定>][<符号>][#][0][<幅>][<グルーピング指定>][.<精度>][<変換型>]
[]は省略可能な部分を示しています。 .format_map()関数¶.format()では 引数に名前付き引数をつかうことで、変換指定文字列中で
出力するデータをその名前で指定することができました。
"{a} {b}".format(a=1,b=2)
'1 2'
名前と値の組み合わせをすでに辞書型データとして持っているときには、.format_mapメソッドを利用できます。
d=dict(a=1,b=2)
"{a} {b}".format_map(d)
'1 2'
"{a} {b}".format(**d)
'1 2'
f"...")¶プログラム実行中に、定義済みの変数の値を印刷することはよくあります。たとえばこんな使い方です。
p=6.62607015e-34
"p={p:g}".format(p=p)
'p=6.62607e-34'
フォーマット済み文字列定数を使うと、次の例のよう簡潔に記述することができます。
from numpy import sqrt
p=6.62607015e-34
f"{p=:g}"
'p=6.62607e-34'
通常の書式指定文字列と同じようにフォーマット済み文字列定数(f"..." or F"...")では、{と}で囲まれた変換指定の部分が実行時のデータに基づいて置き換えられます。
=を追加することで、整形済みの文字列に式=の形の文字列が追加されます。:以降の整形指定は書式指定文字列の場合と同様です。p=6.62607015e-34
f"p={p:g}, {p=:g}, {p**2=:g} {fib(5)=:d}"
'p=6.62607e-34, p=6.62607e-34, p**2=4.39048e-67 fib(5)=8'
フォーマット済み文字列定数を使って、数表印刷プログラムを書き換えてみます。
def 数表の印刷2():
print ("{0:^73s}".format("フィボナッチ数の数表".center(40,"-")))
print ( " {0}".format(
",".join((f" {c:02d}" for c in range(10)))))
for r in range(0,30,10):
print(f"{r:02d}:{{0:s}}".format(
",".join((f"{fib(c):7d}" for c in range(r,r+10)))
))
数表の印刷2()
---------------フィボナッチ数の数表---------------
00, 01, 02, 03, 04, 05, 06, 07, 08, 09
00: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55
10: 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765
20: 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229, 832040
def 数表の印刷():
print ("フィボナッチ数の数表".center(77,"_"))
print ( " {0}".format(
",".join((" {0:02d}".format(c) for c in range(10))))
)
for r in range(0,30,10):
print("{0:02d}:{1}".format(
r,
",".join(("{0:7d}".format(fib(c)) for c in range(r,r+10)))
))
def 数表の印刷2():
print ("{0:^73s}".format("フィボナッチ数の数表".center(40,"-")))
print ( " {0}".format(
",".join((f" {c:02d}" for c in range(10)))))
for r in range(0,30,10):
print(f"{r:02d}:{{0:s}}".format(
",".join((f"{fib(c):7d}" for c in range(r,r+10)))
))
今日の講座では、数表の印刷 を例に
文字型(str)データのメソッド : .join(), .split() など
Unicode文字列(str)とバイト列(bytes) : u"abc" とb"abc"
エスケープ文字列, raw文字列
.encode(), .decode()
文字列の整形(Format)
str型の.format()メソッド
フォーマット済み文字列定数: f""
などについて学びました。